2064 lines
61 KiB
XML
2064 lines
61 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<javascript app="gallery">
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.carousel.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050"><![CDATA[/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.browse.carousel.js - Controller for Gallery carousel
|
|
*
|
|
* Author: Ehren Harber
|
|
*/
|
|
;( function(){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.front.browse.carousel', {
|
|
|
|
initialize () {
|
|
|
|
this.carouselControls = this.scope[0].closest('[data-carousel-controls]');
|
|
this.carousel = document.getElementById(this.carouselControls.dataset.carouselControls);
|
|
|
|
if(this.carouselControls && this.carousel.scrollWidth > this.carousel.clientWidth){
|
|
this.showArrows();
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
this.buttons = this.scope[0].querySelectorAll('[data-carousel-arrow]');
|
|
this.buttons.forEach(button => {
|
|
button.addEventListener('click', this.scrollPanels);
|
|
});
|
|
|
|
},
|
|
|
|
showArrows: function(){
|
|
|
|
this.carouselControls.hidden = false;
|
|
|
|
},
|
|
|
|
scrollPanels: function(ev) {
|
|
|
|
let carouselControls = this.closest('[data-carousel-controls]'),
|
|
carousel = document.getElementById(carouselControls.dataset.carouselControls),
|
|
direction = this.dataset.carouselArrow,
|
|
currentScroll = carousel.scrollLeft,
|
|
scrollByVar = getComputedStyle(carousel).getPropertyValue('--carousel--scroll'),
|
|
carouselChildWidth = carousel.firstElementChild.offsetWidth,
|
|
scrollBy = scrollByVar * (carouselChildWidth);
|
|
|
|
if (direction == 'prev'){
|
|
scrollBy = -scrollBy;
|
|
}
|
|
if (currentScroll == '0' && direction == 'prev'){
|
|
carousel.scrollLeft = carousel.scrollWidth;
|
|
} else if ((currentScroll == carousel.scrollWidth - carousel.clientWidth) && (direction == 'next')){
|
|
carousel.scrollLeft = 0;
|
|
} else {
|
|
carousel.scrollLeft = currentScroll + scrollBy;
|
|
}
|
|
},
|
|
|
|
});
|
|
}());]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.list.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050">/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.browse.list.js - Gallery browse list controller
|
|
*
|
|
* Author: Rikki Tissier
|
|
*/
|
|
;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.front.browse.list', {
|
|
|
|
initialize: function () {
|
|
this.on( 'change', '[data-role="moderation"]', this.selectImage );
|
|
},
|
|
|
|
/**
|
|
* Toggles classes when the moderation checkbox is checked
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
selectImage: function (e) {
|
|
var row = $( e.currentTarget ).closest('.cGalleryImageItem');
|
|
row.toggleClass( 'cGalleryImageItem_selected', $( e.currentTarget ).is(':checked') );
|
|
}
|
|
});
|
|
}(jQuery, _));</file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/global" javascript_name="ips.global.nsfw.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100">;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.front.global.nsfw', {
|
|
|
|
initialize () {
|
|
this.on( 'click', '.ipsImageBlock__nsfw button', this.removeOverlays );
|
|
},
|
|
|
|
removeOverlays( e ) {
|
|
e.preventDefault();
|
|
|
|
var expires = new Date();
|
|
expires.setDate( expires.getDate() + 365 );
|
|
ips.utils.cookie.set( 'nsfwImageOptIn', true, expires.toUTCString() );
|
|
|
|
$('.ipsImageBlock__nsfw').fadeOut(500, function() { this.remove() });
|
|
},
|
|
|
|
});
|
|
|
|
}(jQuery, _));</file>
|
|
<file javascript_app="gallery" javascript_location="admin" javascript_path="controllers/settings" javascript_name="ips.settings.settings.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050">/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.settings.settings.js
|
|
*
|
|
* Author: Brandon Farber
|
|
*/
|
|
;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.admin.settings.settings', {
|
|
alertOpen: false,
|
|
|
|
initialize: function () {
|
|
if( $('input[name=rebuildWatermarkScreenshots]').val() == 0 )
|
|
{
|
|
this.on( 'uploadComplete', '[data-ipsUploader]', this.promptRebuildPreference );
|
|
this.on( 'fileDeleted', this.promptRebuildPreference );
|
|
this.on( 'change', '#gallery_watermark_images input, #form_gallery_large_dims input, #form_gallery_small_dims input, #form_gallery_use_square_thumbnails input', this.promptRebuildPreference );
|
|
}
|
|
},
|
|
|
|
promptRebuildPreference: function (e) {
|
|
|
|
if( this.alertOpen )
|
|
{
|
|
return;
|
|
}
|
|
|
|
this.alertOpen = true;
|
|
|
|
/* Show Rebuild Prompt */
|
|
ips.ui.alert.show({
|
|
type: 'confirm',
|
|
message: ips.getString('rebuildGalleryThumbnails'),
|
|
subText: ips.getString('rebuildGalleryThumbnailsBlurb'),
|
|
icon: 'question',
|
|
buttons: {
|
|
ok: ips.getString('rebuildGalleryThumbnailsYes'),
|
|
cancel: ips.getString('rebuildGalleryThumbnailsNo')
|
|
},
|
|
callbacks: {
|
|
ok: function(){
|
|
$('input[name=rebuildWatermarkScreenshots]').val( 1 );
|
|
this.alertOpen = false;
|
|
},
|
|
cancel: function(){
|
|
$('input[name=rebuildWatermarkScreenshots]').val( 0 );
|
|
this.alertOpen = false;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
});
|
|
}(jQuery, _));</file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.chooseCategory.js" javascript_type="controller" javascript_version="107643" javascript_position="1000150"><![CDATA[/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.submit.chooseCategory.js - AJAX to show album options after selecting category
|
|
*
|
|
* Author: Mark Wade
|
|
*/
|
|
;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.front.submit.chooseCategory', {
|
|
|
|
_chosen: false,
|
|
_resizeTimer: null,
|
|
|
|
initialize: function () {
|
|
this.on( 'nodeItemSelected', '[data-name="image_category"]', this.chooseCategory );
|
|
this.on( 'nodeSelectedChanged', '[data-name="image_category"]', this.chooseCategoryInitially );
|
|
this.on( 'click', '[data-action="continueNoAlbum"]', this.continueNoAlbum );
|
|
this.on( 'click', '[data-type]:not([data-disabled])', this.chooseAlbumType );
|
|
|
|
// Try to set the dialog title
|
|
this.setup();
|
|
|
|
// But in some cases we finish loading before the wrapper controller, so also listen for the wrapper controller to finish
|
|
// and set the title then, if appropriate
|
|
this.on( document, 'gallery.wrapperInit', this.setup );
|
|
},
|
|
|
|
setup: function () {
|
|
// Set the dialog title depending on what's being shown
|
|
if( this.scope.find('[data-role="categoryForm"]').length ){
|
|
this.trigger('gallery.updateTitle', { title: ips.getString('chooseCategory') });
|
|
} else {
|
|
this.trigger('gallery.updateTitle', { title: ips.getString('chooseAlbum') });
|
|
}
|
|
},
|
|
|
|
chooseAlbumType: function (e) {
|
|
e.preventDefault();
|
|
|
|
var target = $( e.currentTarget );
|
|
|
|
switch( target.attr('data-type') ){
|
|
case 'category':
|
|
target.next('form').submit();
|
|
break;
|
|
case 'createAlbum':
|
|
this.trigger('gallery.updateTitle', { title: ips.getString('createAlbum') });
|
|
this._resizeFormDiv( this.scope.find('[data-role="createAlbumForm"]') );
|
|
break;
|
|
case 'existingAlbum':
|
|
this.trigger('gallery.updateTitle', { title: ips.getString('existingAlbum') });
|
|
this._resizeFormDiv( this.scope.find('[data-role="existingAlbumForm"]') );
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Controller destroy handler
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
destroy: function () {
|
|
if( this._resizeTimer ){
|
|
clearInterval( this._resizeTimer );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Resize the dialog to fit the form being shown inside it
|
|
*
|
|
* @param {element} form The form being shown
|
|
* @returns {void}
|
|
*/
|
|
_resizeFormDiv: function (form) {
|
|
this.scope.find('[data-role="chooseAlbumType"]').hide();
|
|
var self = this;
|
|
|
|
var resize = function (animate) {
|
|
var height = form.innerHeight() + 130;
|
|
var submitHeight = form.find('.cGalleryDialog_submitBar').height();
|
|
|
|
if( animate ){
|
|
self.scope.closest('.cGalleryDialog').animate({
|
|
minHeight: ( height + submitHeight ) + 'px'
|
|
});
|
|
} else {
|
|
self.scope.closest('.cGalleryDialog').css({
|
|
minHeight: ( height + submitHeight ) + 'px'
|
|
});
|
|
}
|
|
}
|
|
|
|
form.show().css({
|
|
opacity: "0.001"
|
|
});
|
|
|
|
if( this.scope.closest('.ipsDialog').length ){
|
|
resize(true);
|
|
}
|
|
|
|
form.animate({
|
|
opacity: "1"
|
|
}, function () {
|
|
if( self.scope.closest('.ipsDialog').length ){
|
|
self._resizeTimer = setInterval( function () {
|
|
resize(false);
|
|
}, 500);
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Responds to the initial event put out by the select tree when it selects the default value
|
|
*
|
|
* @param {event} e Event object
|
|
* @param {object} data Event data object
|
|
* @returns {void}
|
|
*/
|
|
chooseCategoryInitially: function (e, data) {
|
|
if( this._chosen ){
|
|
return;
|
|
}
|
|
|
|
if( !_.isArray( data.selectedItems ) ){
|
|
return;
|
|
}
|
|
|
|
var id = data.selectedItems[0];
|
|
|
|
if( !_.isUndefined( id ) ){
|
|
this._chosen = true;
|
|
this.showAlbumOptions( id );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Choose Category
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
chooseCategory: function (e, data) {
|
|
if( this._chosen ){
|
|
return;
|
|
}
|
|
|
|
this._chosen = true;
|
|
this.showAlbumOptions(data.id);
|
|
},
|
|
|
|
/**
|
|
* Continue the wizard without doing an album
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
continueNoAlbum: function (e) {
|
|
e.preventDefault();
|
|
$( e.currentTarget ).closest('form').submit();
|
|
},
|
|
|
|
/**
|
|
* Trigger Category Selection
|
|
*
|
|
* @param {int} id Selected ID
|
|
* @returns {void}
|
|
*/
|
|
showAlbumOptions: function (id) {
|
|
var outerWrapper = this.scope.closest('.ipsDialog_content');
|
|
var self = this;
|
|
|
|
outerWrapper.addClass('ipsLoading');
|
|
this.scope.hide();
|
|
|
|
// Fire AJAX
|
|
ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=gallery&module=gallery&controller=submit&noWrapper=1&category=' + id + '&album=' + this.scope.attr('data-preselected-album') )
|
|
.done( function (response) {
|
|
if( response ){
|
|
self.trigger( 'gallery.submit.response', {
|
|
response: response
|
|
});
|
|
} else {
|
|
self.scope.find('[data-role="continueCategory"]').show();
|
|
}
|
|
})
|
|
.fail(function(err){
|
|
self.scope.find('[data-role="continueCategory"]').show();
|
|
})
|
|
.always( function() {
|
|
outerWrapper.removeClass('ipsLoading');
|
|
self.scope.show();
|
|
});
|
|
},
|
|
|
|
});
|
|
}(jQuery, _));
|
|
]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.existingAlbums.js" javascript_type="controller" javascript_version="107643" javascript_position="1000150"><![CDATA[/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.submit.existingAlbums.js - Allows user to select an existing gallery album
|
|
*
|
|
* Author: Rikki Tissier
|
|
*/
|
|
;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.front.submit.existingAlbums', {
|
|
/**
|
|
* Initialization method
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
initialize: function () {
|
|
this.on( 'click', '#elGallerySubmit_albumChooser > li', this.clickAlbum );
|
|
this._checkSelected();
|
|
},
|
|
|
|
/**
|
|
* Event handler for clicking an album entry
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
clickAlbum: function (e) {
|
|
$( e.currentTarget ).find('input[type="radio"]').prop( 'checked', true );
|
|
this._checkSelected();
|
|
},
|
|
|
|
/**
|
|
* Checks whether any radios are selected, and enables/disables the submit button as needed
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_checkSelected: function () {
|
|
if( this.scope.find('input[name="existing_album"]:checked').length ){
|
|
this.scope.find('button[type="submit"]').prop( 'disabled', false );
|
|
} else {
|
|
this.scope.find('button[type="submit"]').prop( 'disabled', true );
|
|
}
|
|
}
|
|
});
|
|
}(jQuery, _));]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.uploadImages.js" javascript_type="controller" javascript_version="107643" javascript_position="1000150"><![CDATA[/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.submit.uploadImages.js - Image upload step
|
|
*
|
|
* Author: Rikki Tissier
|
|
*/
|
|
;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.front.submit.uploadImages', {
|
|
|
|
initialize: function () {
|
|
// Handle clicks on 'upload' field
|
|
var self = this;
|
|
this.scope.find('.ipsAttachment_dropZone').on( 'click', function(e){
|
|
// This is here to prevent the file dialog opening twice due to the click triggered below (which is inside ipsAttachment_dropZone)
|
|
e.stopPropagation();
|
|
|
|
if( !$( e.target ).is('input') )
|
|
{
|
|
self.scope.find('input[type="file"]').trigger('click');
|
|
}
|
|
} );
|
|
|
|
this.on( 'fileAdded', '[data-ipsUploader]', this.filesAdded );
|
|
this.on( 'uploadComplete', '[data-ipsUploader]', this.uploadComplete );
|
|
this.on( 'fileDeleted', '[data-ipsUploader]', this.fileRemoved );
|
|
this.setup();
|
|
},
|
|
|
|
/**
|
|
* Setup method
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
setup: function () {
|
|
// Disable the submit button if we have no files
|
|
if( !this.scope.find('[data-role="fileList"] [data-role="file"]').length ) {
|
|
this.scope.find('[data-role="submitForm"]').prop( 'disabled', true );
|
|
}
|
|
|
|
// Make sure bottom submit bar is showing
|
|
$('.cGallerySubmit_bottomBar').removeClass('ipsHide');
|
|
|
|
// We want to move the allowed types of files span
|
|
$('[data-role="allowedTypes"]').html( this.scope.find('span.ipsType_light.ipsType_small').html() );
|
|
this.scope.find('span.ipsType_light.ipsType_small').remove();
|
|
|
|
// And change the uploader message
|
|
this.scope.find('.ipsAttachment_supportDrag').html( ips.getString('uploader_add_images') );
|
|
},
|
|
|
|
/**
|
|
* Responds to event from the uploader
|
|
*
|
|
* @param {event} e Event object
|
|
* @param {object} data Data object from uploader
|
|
* @returns {void}
|
|
*/
|
|
fileRemoved: function (e, data) {
|
|
if( data.fileElem.attr('data-fileid').indexOf('o_') != -1 )
|
|
{
|
|
var imageId = $('input[name="images_existing\\[' + data.fileElem.attr('data-fileid') + '\\]"').val();
|
|
}
|
|
else
|
|
{
|
|
var imageId = data.fileElem.attr('data-fileid');
|
|
}
|
|
|
|
// If we've already built the image form, remove it
|
|
if( $('#image_details_' + imageId ).length )
|
|
{
|
|
$('#image_details_' + imageId ).remove();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Uploader has told us all uploads are complete
|
|
*
|
|
* @param {event} e Event object
|
|
* @param {objct} data Data object from uploader
|
|
* @returns {void}
|
|
*/
|
|
uploadComplete: function (e, data) {
|
|
if( data.success > 0 ){
|
|
this.trigger('gallery.activateSubmitButton');
|
|
}
|
|
|
|
if( data.error > 0 ){
|
|
this.trigger('gallery.uploadErrors');
|
|
}
|
|
|
|
if( !this.sortableInitialized ){
|
|
// And allow images to be reordered
|
|
this.scope.find('[data-role="fileList"] > .cGallerySubmit_fileList').sortable({
|
|
forcePlaceholderSize: true
|
|
});
|
|
|
|
this.sortableInitialized = true;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Track whether we've initialized the sortable
|
|
*/
|
|
sortableInitialized: false,
|
|
|
|
/**
|
|
* Responds to event from the uploader
|
|
*
|
|
* @param {event} e Event object
|
|
* @param {object} data Data object from uploader
|
|
* @returns {void}
|
|
*/
|
|
filesAdded: function (e, data) {
|
|
this.trigger('gallery.disableSubmitButton');
|
|
|
|
$('[data-role="addFiles"]').removeClass( 'ipsHide' );
|
|
$('[data-role="imageDetails"]').removeClass('ipsHide');
|
|
|
|
// Only add the uploadStep class if we aren't on mobile
|
|
if( !ips.utils.responsive.enabled() || !ips.utils.responsive.currentIs('phone') ){
|
|
this.scope.closest('.cGalleryDialog').addClass('cGalleryDialog_uploadStep');
|
|
}
|
|
|
|
$( window ).trigger('resize');
|
|
}
|
|
});
|
|
}(jQuery, _));]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.wrapper.js" javascript_type="controller" javascript_version="107643" javascript_position="1000150"><![CDATA[/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.submit.main.js - Main gallery submit dialog controller
|
|
*
|
|
* Author: Rikki Tissier
|
|
*/
|
|
;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
ips.controller.register('gallery.front.submit.wrapper', {
|
|
|
|
_expanded: false,
|
|
_currentErrors: {},
|
|
|
|
/**
|
|
* Initialize the controller
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
initialize: function () {
|
|
// Intercept form submissions
|
|
this.on( 'submit', 'form', this.submitForm );
|
|
this.on( 'click', '[data-role="submitForm"]', this.maybeSubmitForm );
|
|
|
|
// If another controller tells us to do something, do it
|
|
this.on( 'gallery.submit.response', this._updateWrapper );
|
|
|
|
// Handle uploader "clicks"
|
|
this.on( 'click', '[data-role="addFiles"]', this.dropzoneClick );
|
|
this.on( 'click', '[data-action="closeDialog"]', this.confirmClose );
|
|
|
|
// Handle image details
|
|
this.on( 'click', '[data-role="file"][data-fileid]', this.setUpImageDetailsForm );
|
|
this.on( 'click', '[data-role="imageDescriptionUseEditor"]', this.setUpImageDescriptionRich );
|
|
this.on( 'click', '[data-role="imageDescriptionUseTextarea"]', this.setUpImageDescriptionPlain );
|
|
this.on( 'click', '[data-role="addCopyrightCredit"]', this.showCopyrightCredit );
|
|
this.on( 'click', '[data-role="saveDetails"]', this.saveDetails );
|
|
this.on( 'click', '[data-role="saveInfo"]', this.saveInfo );
|
|
|
|
// Handle events from uploader
|
|
this.on( 'gallery.activateSubmitButton', this.activateSubmitButton );
|
|
this.on( 'gallery.disableSubmitButton', this.disableSubmitButton );
|
|
this.on( 'gallery.uploadErrors', this.uploadErrors );
|
|
this.on( 'gallery.enlargeUploader', this.enlargeUploader );
|
|
this.on( 'gallery.updateTitle', this.updateTitle );
|
|
|
|
// Set us up
|
|
this.setup();
|
|
|
|
// Let everyone know we're done in case they're waiting
|
|
this.trigger('gallery.wrapperInit');
|
|
},
|
|
|
|
/**
|
|
* Setup method
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
setup: function () {
|
|
// On initial load, destroy the ckeditor object as it will be recreated for each individual form
|
|
ips.ui.editor.destruct( this.scope.find('[data-ipseditor]') );
|
|
|
|
if( this.scope.find('.cGalleryDialog_imageForm').is(':visible') ){
|
|
this._enlargeUploadStep();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler, allows other controllers to update the title
|
|
*
|
|
* @param {string} url URL to call
|
|
* @param {object} data Data to pass to ajax handler
|
|
* @returns {void}
|
|
*/
|
|
updateTitle: function (e, data) {
|
|
if( data.title ){
|
|
this._updateTitle( data.title );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Actually updates the title of the dialog
|
|
*
|
|
* @param {string} url URL to call
|
|
* @param {object} data Data to pass to ajax handler
|
|
* @returns {void}
|
|
*/
|
|
_updateTitle: function (title) {
|
|
this.scope.find('[data-role="dialogTitle"]').text( title );
|
|
},
|
|
|
|
/**
|
|
* Event handler for when another controller needs to enlarge the uploader
|
|
*
|
|
* @param {string} url URL to call
|
|
* @param {object} data Data to pass to ajax handler
|
|
* @returns {void}
|
|
*/
|
|
enlargeUploader: function (e, data) {
|
|
this._enlargeUploadStep( data.callback || $.noop );
|
|
},
|
|
|
|
/**
|
|
* Enable the submit button
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
activateSubmitButton: function () {
|
|
this.scope.find('[data-role="submitForm"]').prop( 'disabled', false );
|
|
},
|
|
|
|
/**
|
|
* Disable the submit button
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
disableSubmitButton: function () {
|
|
this.scope.find('[data-role="submitForm"]').prop( 'disabled', true );
|
|
},
|
|
|
|
/**
|
|
* Uploader encounted errors; show message
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
uploadErrors: function () {
|
|
this.scope.find('[data-role="imageErrors"]').show();
|
|
},
|
|
|
|
/**
|
|
* Handles a click on the dropzone, to trigger the Add Files dialog
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
dropzoneClick: function() {
|
|
this.scope.find('.ipsAttachment_dropZone').trigger('click');
|
|
},
|
|
|
|
/**
|
|
* Handles a click on the dropzone, to trigger the Add Files dialog
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
showCopyrightCredit: function (e) {
|
|
e.preventDefault();
|
|
var link = $( e.currentTarget );
|
|
link.hide().next().slideDown();
|
|
},
|
|
|
|
/**
|
|
* Closes the copyright/credit menu
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
saveInfo: function (e) {
|
|
e.preventDefault();
|
|
$(e.currentTarget).trigger('closeMenu');
|
|
},
|
|
|
|
/**
|
|
* Mobile-specific functionality for 'save' button
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
saveDetails: function (e) {
|
|
if( e ){
|
|
e.preventDefault();
|
|
}
|
|
|
|
this._markActiveImageAsSaved();
|
|
|
|
// Show and then hide a 'saved' message
|
|
$(e.currentTarget).next('[data-role="savedMessage"]').fadeIn();
|
|
setTimeout( function () {
|
|
$(e.currentTarget).next('[data-role="savedMessage"]').fadeOut();
|
|
}, 2000 );
|
|
|
|
// Hide any error messages
|
|
if( e ){
|
|
$( e.currentTarget ).closest('.cGallerySubmit_details').find('[data-errorField]').hide();
|
|
}
|
|
|
|
// Mobile-only behavior
|
|
if( ips.utils.responsive.enabled() && ips.utils.responsive.currentIs('phone') ){
|
|
// Fade out details form
|
|
this._toggleDetailsPanelMobile(false);
|
|
// Remove active selection styles
|
|
this.scope.find('.cGallerySubmit_activeFile').removeClass('cGallerySubmit_activeFile');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Confirm the user wants to close the dialog
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
confirmClose: function (e) {
|
|
// If there are no images uploaded, let's not bother with a confirmation
|
|
if( !this.scope.find('[data-fileid]').length )
|
|
{
|
|
this.trigger('closeDialog');
|
|
return;
|
|
}
|
|
|
|
if( e ){
|
|
e.preventDefault();
|
|
}
|
|
|
|
var self = this;
|
|
|
|
ips.ui.alert.show( {
|
|
type: 'confirm',
|
|
icon: 'question',
|
|
message: ips.getString('confirmSubmitClose'),
|
|
callbacks: {
|
|
ok: function () {
|
|
self.trigger('closeDialog');
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Marks the currently-active image as 'saved'
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_markActiveImageAsSaved: function () {
|
|
this.scope.find('.cGallerySubmit_activeFile').removeClass('cGallerySubmit_imageError').addClass('cGallerySubmit_imageSaved');
|
|
},
|
|
|
|
/**
|
|
* Set up image details form
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
setUpImageDetailsForm: function (e) {
|
|
|
|
// Remove selection from all other files
|
|
this.scope.find('.cGallerySubmit_activeFile').removeClass('cGallerySubmit_activeFile');
|
|
$( e.currentTarget ).addClass('cGallerySubmit_activeFile');
|
|
|
|
// Get the image ID first
|
|
if( $( e.currentTarget ).attr('data-fileid').indexOf('o_') != -1 )
|
|
{
|
|
var imageId = $('input[name="images_existing\\[' + $( e.currentTarget ).attr('data-fileid') + '\\]"').val();
|
|
}
|
|
else
|
|
{
|
|
var imageId = $( e.currentTarget ).attr('data-fileid');
|
|
}
|
|
|
|
var imagePreview = $( e.currentTarget ).find('.ipsImage').attr('src');
|
|
var detailsPanel = this.scope.find('[data-role="imageDetails"]');
|
|
|
|
// Hide our existing form, if any
|
|
detailsPanel.find('.cGallerySubmit_details, [data-role="submitHelp"]').hide();
|
|
|
|
// If we've already built the image form, just show it
|
|
if( $('#image_details_' + imageId ).length ){
|
|
$('#image_details_' + imageId + ' .cGallerySubmit_details' ).show();
|
|
|
|
if( ips.utils.responsive.currentIs('phone') ){
|
|
this._toggleDetailsPanelMobile(true);
|
|
}
|
|
} else {
|
|
// Otherwise, clone our existing form to use
|
|
$('[data-role="defaultImageDetailsForm"]').find('#cke_filedata__image_description_DEFAULT').remove();
|
|
var htmlToInsert = $('[data-role="defaultImageDetailsForm"]').html();
|
|
htmlToInsert = '<div id="image_details_' + imageId + '">' + htmlToInsert.replace( /name="image_tags_DEFAULT"/g, 'name="image_tags_DEFAULT" data-ipsAutocomplete ').replace( /_DEFAULT/g, '_' + imageId ) + "</div>";
|
|
|
|
// Now insert this form
|
|
detailsPanel.find('> form').prepend( htmlToInsert );
|
|
|
|
var imageForm = $('#image_details_' + imageId );
|
|
|
|
// Set the image caption
|
|
var filename = $( e.currentTarget ).find('[data-role="title"]').text();
|
|
var filenameWithoutExt = filename.replace(/\.[^/.]+$/, '');
|
|
$('#elInput_image_title_' + imageId ).val( filenameWithoutExt );
|
|
|
|
// Fix yes/no fields as they will reinitialize and break
|
|
detailsPanel.find('> form #image_details_' + imageId ).find('.ipsToggle').remove();
|
|
|
|
if( !_.isUndefined( imagePreview ) ){
|
|
imageForm
|
|
.find('.cGallerySubmit_preview')
|
|
.removeClass('ipsBox_transparent')
|
|
.removeClass('ipsNoThumb')
|
|
.removeClass('ipsNoThumb_video')
|
|
.html("<img src='" + imagePreview + "' class='ipsImage' />")
|
|
.show();
|
|
|
|
}
|
|
else {
|
|
imageForm
|
|
.find('.cGallerySubmit_preview')
|
|
.addClass('ipsBox_transparent')
|
|
.addClass('ipsNoThumb')
|
|
.addClass('ipsNoThumb_video')
|
|
.html("")
|
|
.show();
|
|
}
|
|
|
|
// If this is a movie, show the thumbnail uploader
|
|
if( !$( e.currentTarget ).attr('data-thumbnailurl') ){
|
|
imageForm.find('.cGalleryThumbField').removeClass('ipsHide');
|
|
} else {
|
|
|
|
// Otherwise if it's an image, find out if we have GPS info and need to let them toggle map on/off
|
|
ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=gallery&module=gallery&controller=submit&do=checkGps&imageId=' + imageId, {
|
|
type: 'get',
|
|
bypassRedirect: true
|
|
})
|
|
.done( function (response, status, jqXHR) {
|
|
// Just find the internal content
|
|
if( parseInt( response.hasGeo ) ){
|
|
imageForm.find('.cGalleryMapField').removeClass('ipsHide');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Show the details panel if we're on mobile
|
|
if( ips.utils.responsive.currentIs('phone') ){
|
|
this._toggleDetailsPanelMobile(true);
|
|
}
|
|
|
|
// And then emit contentChange event to trigger javascript controllers (e.g. tags)
|
|
$( document ).trigger( 'contentChange', [ $('[data-role="imageDetails"] > form') ] );
|
|
|
|
// Check for current errors
|
|
if( !_.isUndefined( this._currentErrors[ imageId ] ) ){
|
|
this._updateDetailsWithErrors( imageId, this._currentErrors[ imageId ] );
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Toggle details panel on mobile
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_toggleDetailsPanelMobile: function (show) {
|
|
var detailsPanel = this.scope.find('[data-role="imageDetails"]');
|
|
|
|
if( !show ){
|
|
detailsPanel
|
|
.animate({
|
|
opacity: "0",
|
|
top: '400px'
|
|
}, 400, function () {
|
|
detailsPanel.hide()
|
|
});
|
|
} else if( !detailsPanel.is(':visible') ) {
|
|
detailsPanel
|
|
.show()
|
|
.css({
|
|
opacity: "0",
|
|
top: '400px'
|
|
})
|
|
.animate({
|
|
opacity: "1",
|
|
top: '0px'
|
|
}, 400 );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Set up description events
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
setUpImageDescriptionRich: function(e) {
|
|
var currentDescription = $( e.currentTarget ).closest('[data-role="imageDescriptionTextarea"]')
|
|
.find( '> textarea' )
|
|
.val()
|
|
.trim();
|
|
if( currentDescription.length ){
|
|
var editorObj = ips.ui.editor.getObj( $( e.currentTarget ).closest('[data-role="imageDescriptionTextarea"]')
|
|
.prev('[data-role="imageDescriptionEditor"]')
|
|
.find('[data-ipseditor]') );
|
|
var editorInstance = editorObj.getInstance();
|
|
editorInstance.setData( currentDescription );
|
|
$( e.currentTarget ).closest('[data-role="imageDescriptionTextarea"]')
|
|
.find( '> textarea' )
|
|
.val('');
|
|
}
|
|
|
|
$( e.currentTarget ).closest('[data-role="imageDescriptionTextarea"]')
|
|
.addClass('ipsHide')
|
|
.prev('[data-role="imageDescriptionEditor"]')
|
|
.removeClass('ipsHide');
|
|
|
|
e.preventDefault();
|
|
},
|
|
|
|
/**
|
|
* Set up description events
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
setUpImageDescriptionPlain: function (e) {
|
|
var editorObj = ips.ui.editor.getObj( $( e.currentTarget ).closest('[data-role="imageDescriptionEditor"]')
|
|
.find('[data-ipseditor]') );
|
|
var currentDescription = $( editorObj.getInstance().getData() ).text()
|
|
.trim();
|
|
if( currentDescription.length ){
|
|
$( e.currentTarget ).closest('[data-role="imageDescriptionEditor"]')
|
|
.next('[data-role="imageDescriptionTextarea"]')
|
|
.find( 'textarea' )
|
|
.val( currentDescription );
|
|
}
|
|
|
|
$( e.currentTarget ).closest('[data-role="imageDescriptionEditor"]')
|
|
.addClass('ipsHide')
|
|
.next('[data-role="imageDescriptionTextarea"]')
|
|
.removeClass('ipsHide');
|
|
|
|
e.preventDefault();
|
|
},
|
|
|
|
/**
|
|
* IE11 doesn't support submit buttons outside of a <form> like HTML5 does.
|
|
* So, if we click the button, are on IE11, and not inside a form, manually trigger a submit.
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
maybeSubmitForm: function (e) {
|
|
var isIE11 = !(window.ActiveXObject) && "ActiveXObject" in window;
|
|
|
|
if( !$( e.currentTarget ).closest('form').length && $( e.currentTarget ).is('[form]') && isIE11 ){
|
|
var form = $('#' + $( e.currentTarget ).attr('form'));
|
|
|
|
if( form.length ){
|
|
form.submit();
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for submitting forms inside the wizard
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
submitForm: function (e) {
|
|
e.preventDefault();
|
|
|
|
var form = $( e.currentTarget );
|
|
var url = form.attr('action');
|
|
|
|
// If we are submitting images, get the info we need
|
|
if( form.attr('id') == 'elGallerySubmit' ){
|
|
// Sync editor to its textarea
|
|
this.scope.find('[data-ipseditor]').each( function(){
|
|
try {
|
|
var editorObj = ips.ui.editor.getObj( $( this ) );
|
|
var editorInstance = editorObj.getInstance();
|
|
|
|
$( this ).find('textarea[data-role="contentEditor"]').val( editorInstance.getData() );
|
|
} catch (err) {
|
|
Debug.error("Couldn't update textarea from editor");
|
|
}
|
|
});
|
|
|
|
// Get credit, copyright and auto-follow fields and add to our form
|
|
form.find('textarea[name="credit_all"]').val( $('#elTextarea_image_credit_info').val() );
|
|
form.find('textarea[name="copyright_all"]').val( $('#elInput_image_copyright').val() );
|
|
|
|
if( $('#elInput_image_tags_wrapper').length ){
|
|
try {
|
|
var tags = ips.ui.autocomplete.getObj( this.scope.find('#elInput_image_tags') ).getTokens();
|
|
form.find('textarea[name="tags_all"]').val( tags.join("\n") );
|
|
form.find('textarea[name="prefix_all"]').val( $('[name="image_tags_prefix"]').val() );
|
|
} catch (err) {
|
|
Debug.error("Couldn't update tags");
|
|
}
|
|
}
|
|
|
|
if( ips.getSetting('memberID') )
|
|
{
|
|
form.find('input[name="images_autofollow_all"]').val( $('#check_image_auto_follow_wrapper').hasClass('ipsToggle_on') ? 1 : 0 );
|
|
}
|
|
|
|
if( $('#check_image_nsfw_wrapper').length )
|
|
{
|
|
form.find('input[name="nsfw_all"]').val($('#check_image_nsfw_wrapper').hasClass('ipsToggle_on') ? 1 : 0);
|
|
}
|
|
|
|
// Get the order of the images and store this in the submission
|
|
var imageOrder = [];
|
|
|
|
form.find('[data-role="file"]').each( function(){
|
|
if( $(this).attr('data-fileid').indexOf('o_') != -1 )
|
|
{
|
|
imageOrder.push( $('input[name="images_existing\\[' + $(this).attr('data-fileid') + '\\]"').val() );
|
|
}
|
|
else
|
|
{
|
|
imageOrder.push( $(this).attr('data-fileid') );
|
|
}
|
|
});
|
|
|
|
form.find('textarea[name="images_order"]').val( JSON.stringify( imageOrder ) );
|
|
|
|
// And get the individual image details and store in the submission
|
|
form.find('textarea[name="images_info"]').val( JSON.stringify( $('#form_imageDetails').serializeArray() ) );
|
|
|
|
// Hide/disable some stuff
|
|
this.scope.find('[data-role="imageDetails"]').addClass('ipsHide');
|
|
this.scope.find('#elGallerySubmit_toolBar').hide();
|
|
this.scope.find('[data-role="submitForm"]').prop('disabled', true);
|
|
this.scope.find('.cGalleryDialog').removeClass('cGalleryDialog_uploadStep');
|
|
}
|
|
|
|
// And don't bubble up
|
|
e.stopPropagation();
|
|
|
|
this._changeContents( url, form.serialize() );
|
|
},
|
|
|
|
/**
|
|
* Updates the wizard contents from a URL response
|
|
*
|
|
* @param {string} url URL to call
|
|
* @param {object} data Data to pass to ajax handler
|
|
* @returns {void}
|
|
*/
|
|
_changeContents: function (url, data) {
|
|
if( _.isUndefined( data ) ){
|
|
data = {};
|
|
}
|
|
|
|
var self = this;
|
|
var loadingElement = this.scope.closest('.ipsDialog_content');
|
|
|
|
this.scope.find('.cGalleryDialog_container, .cGalleryDialog_imageForm').hide();
|
|
|
|
this.cleanContents();
|
|
loadingElement.addClass('ipsLoading');
|
|
|
|
ips.getAjax()( url + '&noWrapper=1', {
|
|
data: data,
|
|
type: 'post',
|
|
bypassRedirect: true
|
|
})
|
|
.done( function (response, status, jqXHR) {
|
|
// Just find the internal content
|
|
self._updateContents( response );
|
|
})
|
|
.always( function() {
|
|
loadingElement.removeClass('ipsLoading');
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Event listener for passing through AJAX responses
|
|
*
|
|
* @param {object} response AJAX response object
|
|
* @returns {void}
|
|
*/
|
|
_updateWrapper: function( e, data ) {
|
|
this._updateContents( data.response );
|
|
},
|
|
|
|
/**
|
|
* Updates the wizard contents
|
|
*
|
|
* @param {object} response Response object
|
|
* @returns {void}
|
|
*/
|
|
_updateContents: function ( response ) {
|
|
|
|
var wrapper = $('[data-role="submitWrapper"]');
|
|
var container = wrapper.find('[data-role="container"]');
|
|
|
|
if( response.container ) {
|
|
container.html( response.container );
|
|
container.show();
|
|
} else {
|
|
container.hide();
|
|
}
|
|
|
|
if( response.containerInfo ) {
|
|
wrapper.find('[data-role="containerInfo"]').html( response.containerInfo );
|
|
}
|
|
|
|
if( response.images ) {
|
|
this._updateTitle( ips.getString('addImages') );
|
|
// Animate the dialog expanding for the upload step
|
|
if( this.scope.closest('.cGalleryDialog_outer').length && !this.scope.find('[data-role="imagesForm"]').is(':visible') && !this._expanded ){
|
|
this._enlargeUploadStep( function () {
|
|
wrapper.find('[data-role="imageForm"]').html( response.images );
|
|
});
|
|
} else {
|
|
wrapper.find('[data-role="images"]').show();
|
|
wrapper.find('[data-role="imageForm"]').html( response.images );
|
|
}
|
|
}
|
|
|
|
if( response.imageTags && wrapper.find('.cGalleryTagsField').hasClass('ipsHide') ){
|
|
wrapper.find('.cGalleryTagsField').removeClass('ipsHide');
|
|
wrapper.find('.cGalleryTagsField .ipsFieldRow_content').append( response.imageTags );
|
|
}
|
|
|
|
if( response.tagsField && wrapper.find('.cGalleryTagsButton').hasClass('ipsHide') ) {
|
|
wrapper.find('.cGalleryTagsButton').removeClass('ipsHide');
|
|
wrapper.find('[data-role="globalTagsField"]').append( response.tagsField );
|
|
}
|
|
|
|
$( document ).trigger( 'contentChange', [ wrapper ] );
|
|
|
|
if( !_.isUndefined( response.imageErrors ) && _.size( response.imageErrors ) > 0 ){
|
|
this._handleUploaderErrors( response.imageErrors );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles a submission error
|
|
*
|
|
* @param {object} errors Object containing errors
|
|
* @returns {void}
|
|
*/
|
|
_handleUploaderErrors: function (errors) {
|
|
var self = this;
|
|
this.scope.find('[data-role="imageDetails"]').removeClass('ipsHide');
|
|
this.scope.find('#elGallerySubmit_toolBar').show();
|
|
this.scope.find('[data-role="submitForm"]').prop('disabled', false);
|
|
this.scope.find('.cGalleryDialog').addClass('cGalleryDialog_uploadStep');
|
|
|
|
this._currentErrors = errors;
|
|
|
|
var errorCount = _.size( errors );
|
|
var errorIDs = _.keys( errors );
|
|
var errorFileIDs = _.map( errorIDs, function (id) {
|
|
if( self.scope.find('input[type="hidden"][value="' + id + '"]').attr('name') )
|
|
{
|
|
return '#' + self.scope.find('input[type="hidden"][value="' + id + '"]').attr('name').replace(/images_existing\[/g, '').replace(/\]/g, '');
|
|
}
|
|
});
|
|
var errorFileThumbs = this.scope.find( errorFileIDs.join(',') );
|
|
|
|
// Mark all thumbs as 'done'
|
|
this.scope.find('.cGallerySubmit_fileList [data-role="file"]').addClass('cGallerySubmit_imageSaved');
|
|
|
|
// Add error class to all the errored ones
|
|
errorFileThumbs.addClass('cGallerySubmit_imageError').removeClass('cGallerySubmit_imageSaved');
|
|
|
|
_.each( errorIDs, function (id) {
|
|
if( self.scope.find('#image_details_' + id).length ){
|
|
self._updateDetailsWithErrors( id, errors[ id ] );
|
|
}
|
|
});
|
|
|
|
// Show an error
|
|
if( !_.isUndefined( errors[0] ) && !_.isUndefined( errors[0]['images'] ) )
|
|
{
|
|
ips.ui.alert.show( {
|
|
type: 'alert',
|
|
icon: 'warn',
|
|
message: errors[0]['images'],
|
|
});
|
|
}
|
|
else
|
|
{
|
|
ips.ui.alert.show( {
|
|
type: 'alert',
|
|
icon: 'warn',
|
|
message: ips.pluralize( ips.getString('imageUploadErrors'), errorCount ),
|
|
subText: ips.pluralize( ips.getString('imageUploadErrorsDesc'), errorCount )
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Updates the details panel for a file with the provided errors
|
|
*
|
|
* @param {object} errors Object containing errors
|
|
* @returns {void}
|
|
*/
|
|
_updateDetailsWithErrors: function (fileID, errors) {
|
|
var panel = this.scope.find('#image_details_' + fileID);
|
|
|
|
_.each( errors, function (error, field) {
|
|
panel.find('[data-errorField="' + field + '"]').text( error ).show();
|
|
|
|
if( field == 'image_tags' || field == 'image_credit' || field == 'image_copyright' ){
|
|
panel.find('[data-errorField="' + field + '"]').closest('.ipsFieldRow').find('[data-role="addCopyrightCredit"]').click();
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Expands the dialog for the upload step
|
|
*
|
|
* @param {object} response Response object
|
|
* @returns {void}
|
|
*/
|
|
_enlargeUploadStep: function (callback) {
|
|
var wrapper = $('[data-role="submitWrapper"]');
|
|
var dialogElem = this.scope.closest('.cGalleryDialog_outer > div');
|
|
|
|
if( dialogElem.length )
|
|
{
|
|
var dialogElemPos = ips.utils.position.getElemPosition( dialogElem );
|
|
var viewportSize = { width: $( window ).width(), height: $( window ).height() };
|
|
var left = ( viewportSize.width - dialogElem.width() ) / 2;
|
|
|
|
// Set the size of the dialog div, and then animate expanding to fullscreen size
|
|
this.scope.closest('.cGalleryDialog_outer > div').css({
|
|
width: 'auto',
|
|
maxWidth: '100%',
|
|
position: 'fixed',
|
|
margin: 0,
|
|
top: dialogElemPos.absPos.top + 'px',
|
|
left: left + 'px',
|
|
right: viewportSize.width - ( left + dialogElem.width() ) + 'px'
|
|
}).animate({
|
|
left: '10px',
|
|
right: '10px',
|
|
bottom: '10px',
|
|
top: '10px',
|
|
}, function () {
|
|
|
|
// Now fade in the wrapper
|
|
wrapper.find('[data-role="images"]').css({
|
|
opacity: "0.0001",
|
|
}).show();
|
|
|
|
if( callback ){
|
|
callback();
|
|
}
|
|
|
|
wrapper.find('[data-role="images"]').animate({
|
|
opacity: "1"
|
|
});
|
|
|
|
$( document ).trigger( 'contentChange', [ wrapper ] );
|
|
});
|
|
}
|
|
else
|
|
{
|
|
if( callback ){
|
|
callback();
|
|
}
|
|
|
|
$( document ).trigger( 'contentChange', [ wrapper ] );
|
|
}
|
|
|
|
// Positioning needed for upload step
|
|
this.scope.find('.cGalleryDialog').css({ minHeight: "0", position: 'absolute', top: "0", left: "0", right: "0", bottom: "0" });
|
|
this.scope.closest('.ipsDialog_content').css({ position: 'absolute', top: "0", left: "0", right: "0", bottom: "0" });
|
|
|
|
if( !wrapper.find('.cGallerySubmit_bottomBar').hasClass('ipsHide') ){
|
|
wrapper.find('.cGallerySubmit_bottomBar').removeClass('ipsHide').fadeIn();
|
|
}
|
|
|
|
this._expanded = true;
|
|
}
|
|
});
|
|
}(jQuery, _));]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.image.js" javascript_type="controller" javascript_version="107643" javascript_position="1000200">/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.view.image.js - Image controller
|
|
*
|
|
* Author: Rikki Tissier
|
|
*/
|
|
;( function($, _, undefined){
|
|
"use strict";
|
|
|
|
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 );
|
|
},
|
|
|
|
/**
|
|
* Adds a classname to wrapper when a menu opens
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
menuOpened: function () {
|
|
this.scope.find('.elGalleryImage').addClass('cGalleryImageHover');
|
|
},
|
|
|
|
/**
|
|
* Removes classname to wrapper when a menu opens
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
menuClosed: function (e) {
|
|
this.scope.find('.elGalleryImage').removeClass('cGalleryImageHover');
|
|
},
|
|
|
|
/**
|
|
* Handles the keyDown event for navigating photos
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
keyDown: function (e) {
|
|
|
|
// Ignore the keypress if we're in a form element
|
|
if( $( e.target ).closest('input, textarea, .ipsComposeArea, .ipsComposeArea_editor').length ){
|
|
return;
|
|
}
|
|
|
|
switch( e.keyCode ){
|
|
case ips.ui.key.LEFT:
|
|
this.scope.find('[data-action="prevMedia"]')[0].click();
|
|
break;
|
|
case ips.ui.key.RIGHT:
|
|
this.scope.find('[data-action="nextMedia"]')[0].click();
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sets the current image as the user's profile picture
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
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;
|
|
});
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Sets the image as a cover photo
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
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;
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Rotates the image
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
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;
|
|
});
|
|
}
|
|
});
|
|
}(jQuery, _));</file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.note.js" javascript_type="controller" javascript_version="107643" javascript_position="1000200"><![CDATA[/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.view.note.js - Note controller
|
|
*
|
|
* Author: Rikki Tissier
|
|
*/
|
|
;( 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 method, builds the note, makes it editable and positions it
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
setup: function () {
|
|
var self = this;
|
|
|
|
// Force disable for mobile as the behavior isn't terribly good on a small device
|
|
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 is a new note, trigger a click on it to put it into editing mode
|
|
if( this.scope.attr('data-noteID') == 'new' ){
|
|
this.scope.find('.cGalleryNote_border').click();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for saving changes to note text
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
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 is a new note, we'll save the position too.
|
|
if( this.scope.attr('data-noteID') == 'new' ){
|
|
savePosition = true;
|
|
}
|
|
|
|
this._saveNote( note, savePosition )
|
|
.done( function () {
|
|
self._note = note;
|
|
self._stopEditing();
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Event handler for cancelling changes to note text
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
cancelNote: function (e) {
|
|
// If this is a new note 'cancel' should actually delete
|
|
if( this.scope.attr('data-noteID') == 'new' ){
|
|
this.deleteNote( e );
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
this.scope.draggable('enable');
|
|
this._stopEditing();
|
|
},
|
|
|
|
/**
|
|
* Event handler for deleting a note. Confirms with user, then triggers ajax request to remove this note
|
|
*
|
|
* @param {event} e Event
|
|
* @returns {void}
|
|
*/
|
|
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();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Mouse enter event; shows the note text after a short delay
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
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') );
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Mouse leave event; hides the note text after a short delay
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
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') );
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for mousing down on the note edit area (textarea and buttons);
|
|
* This is necessary because on mobile, the draggable widget interferes with the controls
|
|
* and makes them unclickable. Instead what we do is disable the draggable onmouseodown so that
|
|
* clicks are registered, and then our save/cancel handlers will renable it.
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
mouseDown: function () {
|
|
// this.scope.draggable('disable');
|
|
},
|
|
|
|
/**
|
|
* Triggered when the user clicks on the note. Puts the note into editing state,
|
|
* and shows a little form to allow the text to be edited
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
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();
|
|
},
|
|
|
|
/**
|
|
* Deletes the note
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_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();
|
|
});
|
|
})
|
|
},
|
|
|
|
/**
|
|
* Saves the note
|
|
*
|
|
* @param {string} noteContent If provided, the updated note text to be saved
|
|
* @param {boolean} savePosition If true, will update the position info for the note
|
|
* @returns {promise}
|
|
*/
|
|
_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 && note ){
|
|
this.scope.find('[data-action="save"]').prop('disabled', true).text( ips.getString('saving_note') );
|
|
}
|
|
|
|
// Send request
|
|
ips.getAjax()( url, {
|
|
data: {
|
|
note: note,
|
|
position: position
|
|
}
|
|
})
|
|
.done( function (response) {
|
|
if( self.scope.find('[data-action="save"]').length && note ){
|
|
self.scope.find('[data-action="save"]').prop( 'disabled', false ).text( 'Save' );
|
|
}
|
|
|
|
// If this was a new note and the server returned an ID, update our attribute
|
|
if( _.isObject( response ) && response.id ){
|
|
self.scope.attr( 'data-noteID', response.id );
|
|
}
|
|
|
|
deferred.resolve();
|
|
})
|
|
.fail( function () {
|
|
deferred.reject();
|
|
});
|
|
|
|
return deferred.promise();
|
|
},
|
|
|
|
/**
|
|
* Gets the position and dims of the note, in percentage values (relative to the image)
|
|
*
|
|
* @returns {string} In format <left>,<top>,<width>,<height>
|
|
*/
|
|
_getPosition: function () {
|
|
var position = [];
|
|
var parent = this.scope.closest('.cGalleryViewImage');
|
|
var notePos = this.scope.position();
|
|
|
|
// Left
|
|
position[0] = ( notePos['left'] / parent.width() ) * 100;
|
|
// Top
|
|
position[1] = ( notePos['top'] / parent.height() ) * 100;
|
|
// Width
|
|
position[2] = ( this.scope.width() / parent.width() ) * 100;
|
|
// Height
|
|
position[3] = ( this.scope.height() / parent.height() ) * 100;
|
|
|
|
return position.join(',');
|
|
},
|
|
|
|
/**
|
|
* Takes note out of editing state
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_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();
|
|
},
|
|
|
|
/**
|
|
* Adds the note text to the note
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_buildNote: function () {
|
|
this.scope.find('.cGalleryNote_note > div').text( this._note );
|
|
},
|
|
|
|
/**
|
|
* When the note is editable, loads jQuery UI and sets up resizable/draggable
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_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 )
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Event handler for start event on Draggable. If we aren't already editing, set a flag so that
|
|
* when we stop dragging, the click doens't incorrectly put note into editing mode
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_startDragging: function () {
|
|
if( !this._editing ){
|
|
this._draggingNotEditing = true;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Saves the current position of the note. Called when resizable or draggable stop
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_updatePosition: function () {
|
|
var self = this;
|
|
|
|
// If the note block is now out of view, flip it to the other side
|
|
var parent = this.scope.closest('.cGalleryViewImage');
|
|
var notePos = this.scope.position();
|
|
|
|
var posLeft = this.scope.find('.cGalleryNote_note').css('left');
|
|
var posRight = this.scope.find('.cGalleryNote_note').css('right');
|
|
|
|
// If the text box is on the right side, and is now past the boundary of the image, flip it to the left side
|
|
if( parseInt( posLeft ) > 0 ) {
|
|
if( notePos['left'] + parseInt( this.scope.width() ) + parseInt( this.scope.find('.cGalleryNote_note').width() ) > parent.width() ) {
|
|
// But don't bother doing it if it will just be off the other side now
|
|
if( notePos['left'] - parseInt( this.scope.find('.cGalleryNote_note').width() ) > 0 ) {
|
|
this.scope.find('.cGalleryNote_note').css( 'left', posRight );
|
|
this.scope.find('.cGalleryNote_note').css( 'right', posLeft );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( notePos['left'] - parseInt( this.scope.find('.cGalleryNote_note').width() ) < 0 ) {
|
|
// Don't flip if it will be off the other side now
|
|
if( notePos['left'] + parseInt( this.scope.width() ) + parseInt( this.scope.find('.cGalleryNote_note').width() ) < parent.width() ) {
|
|
this.scope.find('.cGalleryNote_note').css( 'left', posRight );
|
|
this.scope.find('.cGalleryNote_note').css( 'right', posLeft );
|
|
}
|
|
}
|
|
}
|
|
|
|
// If this is a new note, we don't want to update the position remotely yet.
|
|
// We'll only do that once the note text is saved for the first time.
|
|
if( this.scope.attr('data-noteID') == 'new' ){
|
|
return;
|
|
}
|
|
|
|
this._saveNote( false, true )
|
|
.done( function () {
|
|
|
|
// If we were editing before updating pos/dims, we don't want to run the stop method
|
|
// otherwise changes to the note text will be lost.
|
|
if( !self._editing ){
|
|
self._stopEditing();
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Positions the note based on the attributes on the scope element
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_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');
|
|
|
|
// Position the note
|
|
this.scope.css({
|
|
left: left + '%',
|
|
top: top + '%',
|
|
width: width + '%',
|
|
height: height + '%'
|
|
});
|
|
}
|
|
});
|
|
}(jQuery, _));]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.notes.js" javascript_type="controller" javascript_version="107643" javascript_position="1000200"><![CDATA[/**
|
|
* Invision Community
|
|
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
|
*
|
|
* ips.view.notes.js - Gallery notes controller
|
|
*
|
|
* Author: Rikki Tissier
|
|
*/
|
|
;( 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 method
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
setup: function () {
|
|
var notes;
|
|
|
|
try {
|
|
notes = $.parseJSON( this.scope.attr('data-notesData') );
|
|
} catch (err) {}
|
|
|
|
if( notes && notes.length ){
|
|
this._buildNotes( notes );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds a new note to the image
|
|
*
|
|
* @param {event} e Event object
|
|
* @returns {void}
|
|
*/
|
|
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 ] );
|
|
},
|
|
|
|
/**
|
|
* Builds any existing notes from data attached to our scope element
|
|
*
|
|
* @param {array} notes Array of note data to build from
|
|
* @returns {void}
|
|
*/
|
|
_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, _));]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.browse.js" javascript_type="template" javascript_version="107643" javascript_position="1000250">// Empty</file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.submit.js" javascript_type="template" javascript_version="107643" javascript_position="1000250"><![CDATA[ips.templates.set('gallery.submit.imageItem', " \
|
|
<div class='ipsAttach ipsImageAttach ipsPad_half ipsAreaBackground_light {{#done}}ipsAttach_done{{/done}}' id='{{id}}' data-role='file' data-fileid='{{id}}' data-fullsizeurl='{{imagesrc}}' data-thumbnailurl='{{thumbnail}}' data-isImage='1'>\
|
|
<ul class='ipsList_inline ipsImageAttach_controls'>\
|
|
<li data-role='insert' {{#insertable}}style='display: none'{{/insertable}}><a href='#' data-action='insertFile' class='ipsAttach_selection' data-ipsTooltip title='{{#lang}}insertIntoPost{{/lang}}'><i class='fa fa-plus'></i></a></li>\
|
|
</li>\
|
|
<li class='ipsPos_right' {{#newUpload}}style='display: none'{{/newUpload}} data-role='deleteFileWrapper'>\
|
|
<input type='hidden' name='{{field_name}}_keep[{{id}}]' value='1'>\
|
|
<a href='#' data-role='deleteFile' class='ipsButton ipsButton_verySmall ipsButton_light' data-ipsTooltip title='{{#lang}}attachRemove{{/lang}}'><i class='fa fa-trash-o'></i></a>\
|
|
</li>\
|
|
</ul>\
|
|
<div class='ipsImageAttach_thumb ipsType_center' data-role='preview' data-grid-ratio='65' data-action='insertFile' {{#thumb}}style='background-image: url( \"{{thumbnail}}\" )'{{/thumb}}>\
|
|
{{#status}}\
|
|
<span class='ipsImageAttach_status ipsType_light' data-role='status'>{{{status}}}</span>\
|
|
<span class='ipsAttachment_progress'><span data-role='progressbar'></span></span>\
|
|
{{/status}}\
|
|
{{#thumb}}\
|
|
{{{thumb}}}\
|
|
{{/thumb}}\
|
|
</div>\
|
|
<h2 class='ipsType_reset ipsAttach_title ipsType_medium ipsTruncate ipsTruncate_line cGalleryImageAttach_info' data-role='title'>{{title}}</h2>\
|
|
<p class='ipsType_light cGalleryImageAttach_info'>{{size}} {{#statusText}}· <span data-role='status'>{{statusText}}</span>{{/statusText}}</p>\
|
|
</div>\
|
|
");
|
|
|
|
ips.templates.set('gallery.submit.imageItemWrapper', " \
|
|
<div class='cGallerySubmit_fileList'>{{{content}}}</div>\
|
|
");]]></file>
|
|
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.view.js" javascript_type="template" javascript_version="107643" javascript_position="1000250"><![CDATA[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='ipsList_inline'>\
|
|
<li><button data-action='save' class='ipsButton ipsButton_light ipsButton_verySmall'>{{#lang}}save_note{{/lang}}</button></li>\
|
|
<li><a href='#' data-action='cancel'>{{#lang}}cancel_note{{/lang}}</a></li>\
|
|
</ul>\
|
|
");]]></file>
|
|
<order app="global" path="/dev/js//framework/">templates
|
|
common/ips.loader.js
|
|
common/ui
|
|
common/utils
|
|
common
|
|
controllers</order>
|
|
<order app="global" path="/dev/js//library/">underscore
|
|
jquery
|
|
mustache
|
|
IntersectionObserver
|
|
Debug.js
|
|
app.js</order>
|
|
<order app="global" path="/dev/js//library//jquery">jquery.js
|
|
jquery-migrate.js
|
|
jquery.history.js
|
|
jquery.transform.js</order>
|
|
<order app="global" path="/dev/js//library//linkify">linkify.min.js
|
|
linkify-jquery.min.js</order>
|
|
</javascript>
|