Files
IPB/applications/cms/data/javascript.xml
T
2025-12-19 04:57:54 -08:00

2078 lines
61 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<javascript app="cms">
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/blocks" javascript_name="ips.blocks.form.js" javascript_type="controller" javascript_version="100045" javascript_position="1000050"><![CDATA[/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.blocks.form.js
*
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('cms.admin.blocks.form', {
initialize: function () {
this.on( 'change', '#elSelect_block_template_use_how', this.toggle );
this.on( 'click', '[data-role=viewTemplate]', this.viewTemplate );
if ( this.scope.find('input[name=block_type]:hidden').val() == 'plugin' )
{
this.on( 'click', 'a[id$=form_tab__content]', this.refreshPreview );
this.on( 'click', 'span[data-role=refreshPreview]', this.refreshPreview );
}
$('#elCodemirror_block_content-input').attr('loaded', 'false');
},
/**
* Refreshes block preview
*
* @param {event} e Event object
* @returns {void}
*/
refreshPreview: function () {
if ( ! $('#elPages_block_preview_form').length )
{
$('<form />').attr('method', 'post').attr('id', 'elPages_block_preview_form').attr('target', 'elpages_block_preview').addClass('ipsHide').appendTo( $('body') );
}
var iframe = $('#elpages_block_preview');
var form = $('#elPages_block_preview_form');
form.find('input[type=hidden]').remove();
var newSrc = iframe.attr('data-base-url');
if ( ! iframe.hasClass('ipsLoading') ){
iframe.addClass('ipsLoading');
}
var fields = '';
$.each( this.scope.find('form').serializeArray(), function( i, item )
{
if ( item.name == 'block_content' )
{
item.value = $('#elCodemirror_block_content-input').data('CodeMirrorInstance').getValue();
}
$('<input type="hidden" />').attr("name", item.name).attr("value", item.value).appendTo( form );
fields += item.name + ",";
Debug.log( "Adding " + item.name + " = " + item.value );
} );
form.attr('action', newSrc + '&__nocache=' + Math.random().toString(36).substr(2, 9) + "&_sending=" + fields );
Debug.log( form );
form.submit();
/* Stop links loading stuff when clicked */
iframe.load(function()
{
iframe.removeClass('ipsLoading');
iframe.removeClass('loading');
iframe.contents().find("a").each( function(index)
{
$( this ).on("click", function(event)
{
event.preventDefault();
event.stopPropagation();
} );
} );
} );
},
/**
* View a template. As the title of the method suggests.
*
* @param {event} e Event object
* @returns {void}
*/
viewTemplate: function (e) {
var span = $( e.currentTarget );
var dialogRef = ips.ui.dialog.create({
title: this.scope.find('input[name=block_plugin]').val(),
url: '?app=cms&module=pages&controller=ajax&do=loadTemplate&show=modal&t_location=block&block_app=' + this.scope.find('input[name=block_plugin_app]').val() + '&block_key=' + this.scope.find('input[name=block_plugin]').val() + '&t_key=' + this.scope.find('#elSelect_block_template_id').val(),
forceReload: true,
remoteSubmit: true
});
dialogRef.show();
},
/**
* Toggle event handler
*
* @param {event} e Event object
* @returns {void}
*/
toggle: function (e) {
var thisToggle = $( e.currentTarget );
if ( thisToggle.val() === 'copy' && $('#elCodemirror_block_content-input').attr('loaded') == 'false' )
{
var save = { 't_location': 'block', 't_key': this.scope.find('#elSelect_block_template_id').val(), 'block_key': this.scope.find('input[name=block_plugin]').val(), 'block_app': this.scope.find('input[name=block_plugin_app]').val() };
var self = this;
ips.getAjax()( '?app=cms&module=pages&controller=ajax&do=loadTemplate&show=json', {
dataType: 'json',
data: save,
type: 'post'
} )
.done( function (response) {
/* Update codemirror */
$('#elCodemirror_block_content-input').data('CodeMirrorInstance').setValue( response.template_content );
$('input[name=template_params]').val( response.template_params );
$('#elCodemirror_block_content-input').attr('loaded', 'true');
});
}
}
});
}(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/databases" javascript_name="ips.databases.download.js" javascript_type="controller" javascript_version="100045" javascript_position="1000100">/**
* IPS Social Suite 4
* (c) 2014 Invision Power Services - http://www.invisionpower.com
*
* ips.databases.download.js - Present an alert to the user asking them if they want to build the app first
*
* Author: Rikki Tissier (Good bits), Matt Mecham (bad bits)
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('cms.admin.databases.download', {
initialize: function () {
this.on( 'click', this.launchAlert );
},
/**
* Displays a dialog to the user with 'build and download' and 'download' options
*
* @param {event} e Event object
* @returns {void}
*/
launchAlert: function (e) {
var self = this;
e.preventDefault();
ips.ui.alert.show({
type: 'confirm',
message: ips.getString('cms_download_db_explain'),
icon: 'fa fa-download',
buttons: {
ok: ips.getString('cms_download_db'),
cancel: ips.getString('cancel')
},
callbacks: {
ok: function () {
window.location = self.scope.attr('data-downloadURL');
},
}
});
}
});
}(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/databases" javascript_name="ips.databases.form.js" javascript_type="controller" javascript_version="100045" javascript_position="1000100">/**
* IPS Social Suite 4
* (c) 2014 Invision Power Services - http://www.invisionpower.com
*
* ips.databases.form.js
*
* Author: Matt Mecham
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('cms.admin.databases.form', {
initialize: function () {
this.on( 'change', '[name=database_create_page]', this.toggle );
this.on( 'change', '[name=database_use_categories]', this.toggleUseCategories );
this.toggle();
this.toggleUseCategories();
},
/**
* Toggle use categories
*
* @param {event} e Event object
* @returns {void}
*/
toggleUseCategories: function (e) {
var label = this.scope.find('[data-lang=index_as_categories]');
if ( $('[name=database_use_categories]:checked').val() == 1 )
{
label.html( ips.getString('index_as_categories') );
}
else
{
label.html( ips.getString('index_as_records') );
}
},
/**
* Toggle event handler
*
* @param {event} e Event object
* @returns {void}
*/
toggle: function (e) {
var thisToggle = $('[name=database_create_page]:checked');
$.each( ['details', 'meta'], function( i, row)
{
if ( thisToggle.val() == 'existing' )
{
$('#form_header_content_page_form_tab__' + row ).hide();
}
else
{
$('#form_header_content_page_form_tab__' + row ).show();
}
} );
}
});
}(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/fields" javascript_name="ips.fields.form.js" javascript_type="controller" javascript_version="100045" javascript_position="1000150">/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.fields.form.js
*
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('cms.admin.fields.form', {
currentValue: null,
initialize: function () {
$('#elTextarea_field_default_value').on( 'keypress', this.checkChange );
if ( $('#field_default_update_existing').length )
{
this.currentValue = $('#elTextarea_field_default_value').val();
$('#field_default_update_existing').hide();
}
},
/**
* checkChange handler
*
* @param {event} e Event object
* @returns {void}
*/
checkChange: function (e) {
if ( $('#elTextarea_field_default_value').val() != this.currentValue )
{
$('#field_default_update_existing').show();
}
}
});
}(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/pages" javascript_name="ips.pages.form.js" javascript_type="controller" javascript_version="100045" javascript_position="1000200"><![CDATA[/**
* IPS Social Suite 4
* (c) 2014 Invision Power Services - http://www.invisionpower.com
*
* ips.pages.form.js - Page Form Stuff That I Can't Be Bothered To Type Out Here
*
* Author: Matt Mecham
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('cms.admin.pages.form', {
initialize: function () {
this.on( 'change', '#check_page_ipb_wrapper', this.toggleIPSWrapper );
this.on( 'change', '#elSelect_page_wrapper_template', this.toggleTemplate );
this.on( 'click', '[data-role=viewTemplate]', this.viewTemplate );
/* View template */
if ( this.scope.find('#elSelect_page_wrapper_template').val() == '_none_' )
{
this.scope.find('[data-role=viewTemplate]').hide();
}
/* Includes warning */
if ( $('#check_page_ipb_wrapper').prop('checked') )
{
$('.ipsCmsIncludesMessage').hide();
}
else
{
$('.ipsCmsIncludesMessage').show();
}
},
/**
* View a template. As the title of the method suggests.
*
* @param {event} e Event object
* @returns {void}
*/
viewTemplate: function (e) {
var span = $( e.currentTarget );
var template = this.scope.find('#elSelect_page_wrapper_template').val().split('__');
var dialogRef = ips.ui.dialog.create({
title: this.scope.find('#elSelect_page_wrapper_template option:selected').text(),
url: '?app=cms&module=pages&controller=ajax&do=loadTemplate&show=modal&t_location=page&t_key=' + template[2],
forceReload: true,
remoteSubmit: true
});
dialogRef.show();
},
/**
* Toggle event handler
*
* @param {event} e Event object
* @returns {void}
*/
toggleTemplate: function (e) {
var thisToggle = $( e.currentTarget );
if ( thisToggle.val() == '_none_' )
{
this.scope.find('[data-role=viewTemplate]').hide();
}
else
{
this.scope.find('[data-role=viewTemplate]').show();
}
},
/**
* Toggle event handler
*
* @param {event} e Event object
* @returns {void}
*/
toggleIPSWrapper: function (e) {
var thisToggle = $( e.currentTarget );
if ( thisToggle.prop('checked') )
{
$('.ipsCmsIncludesMessage').hide();
}
else
{
$('.ipsCmsIncludesMessage').show();
}
}
});
}(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="front" javascript_path="controllers/records" javascript_name="ips.records.form.js" javascript_type="controller" javascript_version="100045" javascript_position="1000050"><![CDATA[/**
* IPS Social Suite 4
* (c) 2014 Invision Power Services - http://www.invisionpower.com
*
* ips.databases.form.js
*
* Author: Matt Mecham
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('cms.front.records.form', {
lastChecked: '',
initialize: function () {
$( '#elInput_' + this.scope.attr('data-ipsTitleField') ).on( 'blur', $.proxy( this.updateSlug, this ) );
this.scope.find('button[data-ipsChange]').on( 'click', $.proxy( this.manualToggle, this ) );
this.scope.find('button[data-ipsCancel]').on( 'click', $.proxy( this.manualCancel, this ) );
/* Stuff already populated? */
if ( this.scope.find('input[name=record_static_furl_set_checkbox]').prop('checked') )
{
this.scope.removeClass('ipsHide');
this._show();
}
},
/**
* Hide options
*
* @param {event} e Event object
* @returns {void}
*/
_hide: function() {
this.scope.find('span[data-ipsSlugManual]').addClass('ipsHide');
this.scope.find('span[data-ipsSlugSlug]').removeClass('ipsHide');
this.scope.find('span[data-ipsSlugExt]').removeClass('ipsHide');
this.scope.find('button[data-ipsCancel]').addClass('ipsHide');
this.scope.find('button[data-ipsChange]').removeClass('ipsHide');
this.scope.find('input[name=record_static_furl_set_checkbox]').prop('checked', false);
this.scope.find('input[name=record_static_furl_set]').val(0);
},
/**
* Show options
*
* @param {event} e Event object
* @returns {void}
*/
_show: function() {
this.scope.find('button[data-ipsCancel]').removeClass('ipsHide');
this.scope.find('button[data-ipsChange]').addClass('ipsHide');
this.scope.find('span[data-ipsSlugManual]').removeClass('ipsHide');
this.scope.find('span[data-ipsSlugSlug]').addClass('ipsHide');
this.scope.find('span[data-ipsSlugExt]').addClass('ipsHide');
this.scope.find('input[name=record_static_furl_set_checkbox]').prop('checked', true);
this.scope.find('input[name=record_static_furl_set]').val(1);
},
/**
* Changed ones mind
*
* @param {event} e Event object
* @returns {void}
*/
manualCancel: function (e) {
e.preventDefault();
this._hide();
},
/**
* Enter a manual URL
*
* @param {event} e Event object
* @returns {void}
*/
manualToggle: function (e) {
e.preventDefault();
this._show();
},
/**
* Slug is being updated?
*
* @param {event} e Event object
* @returns {void}
*/
updateSlug: function (e) {
var value = $( '#elInput_' + this.scope.attr('data-ipsTitleField') ).val();
var self = this;
if ( value != this.lastChecked )
{
ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=cms&module=database&controller=ajax&do=makeFurl', {
data: {
slug: value
}
})
.done( function (response) {
self.scope.removeClass('ipsHide');
self.scope.find('span[data-ipsSlugSlug]').html( '/' + response.slug );
});
this.lastChecked = value;
}
}
});
}(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.addForm.js" javascript_type="controller" javascript_version="100045" javascript_position="1000250">/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.templates.addForm.js - Controller for the 'add' form in the template editor
*
* Author: Rikki Tissier
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('core.admin.templates.addForm', {
initialize: function () {
this.on( 'submit', 'form.ipsForm', this.submitForm );
this.on( document, 'fileListRefreshed.templates', this.closeDialog );
},
submitForm: function (e) {
e.preventDefault();
var self = this;
if( !$( e.currentTarget ).attr('data-bypassValidation') ){
// The form hasn't been validated by the genericDialog controller yet, so bail for now
return;
}
// Gather form values and send them
ips.getAjax()( $( e.currentTarget ).attr('action'), {
dataType: 'json',
data: $( e.currentTarget ).serialize(),
type: 'post'
})
.done( function (response) {
self.trigger( 'addedFile.templates', {
type: self.scope.attr('data-type'),
fileID: response.id,
name: response.name
});
});
},
closeDialog: function (e, data) {
this.trigger('closeDialog');
}
});
}(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.conflict.js" javascript_type="controller" javascript_version="100045" javascript_position="1000250">/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.templates.conflict.js - Templates: Parent controller for the template conflict manager
*
* Author: Matt Mecham
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('core.admin.templates.conflict', {
initialize: function () {
this.on( 'click', '.ipsButton', this.makeSelection );
this.setup();
},
setup: function () {
$('span[data-conflict-name] input[type=radio]').hide();
},
/**
* &quot;Use this version&quot; button is clicked
*
* @param {event} e Event object
* @returns {void}
*/
makeSelection: function (e) {
var span = $( e.target ).closest('span');
var radio = $( span ).find('input[type=radio]');
var name = $( span ).attr('data-conflict-name');
var id = $( radio ).attr('name').replace( /conflict_/, '' );
// Button disabled
if ( span.hasClass('ipsButton_disabled') ){
return false;
}
// Undo selection
else if ( span.hasClass('ipsButton_alternate') ){
radio.removeAttr('checked');
span.removeClass('ipsButton_alternate')
.addClass('ipsButton_primary')
.find('strong')
.html( ips.getString('sc_use_this_version') );
$('input[type=radio][name=conflict_' + id + ']').closest('span.ipsButton[data-conflict-name=' + ( name == 'new' ? 'old' : 'new' ) +']').removeClass('ipsButton_disabled');
$('th span[data-conflict-id=' + id + '][data-conflict-name=' + name + ']').removeClass('ipsPos_left ipsBadge ipsBadge_positive');
ips.utils.anim.go( 'blindDown', this.scope.find('div[data-conflict-id=' + id + ']') );
}
// Make selection
else
{
radio.attr('checked', 'checked');
span.removeClass('ipsButton_primary')
.addClass('ipsButton_alternate')
.find('strong')
.html( ips.getString('sc_remove_selection') );
$('input[type=radio][name=conflict_' + id + ']').closest('span.ipsButton[data-conflict-name=' + ( name == 'new' ? 'old' : 'new' ) +']').addClass('ipsButton_disabled');
$('th span[data-conflict-id=' + id + '][data-conflict-name=' + name + ']').addClass('ipsPos_left ipsBadge ipsBadge_positive');
ips.utils.anim.go( 'fadeOut', this.scope.find('div[data-conflict-id=' + id + ']') );
}
}
});
}(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.fileEditor.js" javascript_type="controller" javascript_version="100045" javascript_position="1000250"><![CDATA[/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.templates.fileEditor.js - Templates: controller for the tabbed file editor
*
* Author: Rikki Tissier
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('cms.admin.templates.fileEditor', {
_tabBar: null,
_tabContent: null,
_fileStore: {},
_ajaxURL: '',
_cmInstances: {},
_currentHeight: 0,
_editorPreferences: {
wrap: true,
lines: false
},
initialize: function () {
// Events from elsewhere
this.on( document, 'openFile.templates', this.openFile );
this.on( document, 'variablesUpdated.templates', this.updateVariables );
// Events from within
this.on( 'tabChanged', this.changedTab );
this.on( 'click', '[data-action="closeTab"]', this.closeTab );
this.on( 'click', '[data-action="save"]', this.save );
this.on( 'click', '[data-action="revert"]:not( .ipsButton_disabled )', this.revert );
this.on( 'savedFile.templates', this.updateFile );
this.on( 'revertedFile.templates', this.updateFile );
this.on( 'openDialog', this.openedDialog );
this.on( 'menuItemSelected', this.menuSelected );
// Other setup
this.setup();
},
/**
* Setup method
*
* @returns {void}
*/
setup: function () {
var self = this;
// Set element references
this._tabBar = this.scope.find('#elTemplateEditor_tabbar');
this._tabContent = this.scope.find('#elTemplateEditor_panels');
// Get the current height of the tab bar
this._currentHeight = this._tabBar.outerHeight();
// Set URLs
this._ajaxURL = this.scope.closest('[data-ajaxURL]').attr('data-ajaxURL');
this._normalURL = this.scope.closest('[data-normalURL]').attr('data-normalURL');
// Get the template editor preferences
this._editorPreferences['wrap'] = ips.utils.db.get('templateEditor', 'wrap');
this._editorPreferences['lines'] = ips.utils.db.get('templateEditor', 'lines');
if( this._editorPreferences['wrap'] ){
$('#elTemplateEditor_preferences_menu').find('[data-ipsMenuValue="wrap"]').addClass('ipsMenu_itemChecked');
}
if( this._editorPreferences['lines'] ){
$('#elTemplateEditor_preferences_menu').find('[data-ipsMenuValue="lines"]').addClass('ipsMenu_itemChecked');
}
// Initialize the initial content
this._tabContent.find('[data-group]').each( function (i, item) {
// We need to turn the variables/attributes text input into a hidden field
// We can't simply change the type because IE8 throws a hissy fit, so we'll make a copy
// then remove the original
var original = self._tabContent.find('[data-fileid="' + $( item ).attr('data-fileid') +
'"] input[data-role="variables"]');
if( original.length ){
original.after(
$('<input/>')
.attr( 'type', 'hidden' )
.attr( 'name', original.attr('name') )
.attr( 'value', original.attr('value') )
.attr( 'data-role', 'variables' )
)
original.remove();
}
ips.loader.get( ['core/interface/codemirror/diff_match_patch.js','core/interface/codemirror/codemirror.js'] ).then( function () {
self._initCodeMirror( $( item ).attr('data-fileid'), $( item ).attr('data-type') );
});
});
},
/**
* Event handler for the editor preference menu
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
menuSelected: function (e, data) {
if( data.originalEvent ){
data.originalEvent.preventDefault();
}
if( data.triggerID == 'elTemplateEditor_preferences' ){
if( data.selectedItemID == 'wrap' ){
this._changeEditorPreference( !ips.utils.db.get('templateEditor', 'wrap'), 'wrap', 'lineWrapping' );
} else {
this._changeEditorPreference( !ips.utils.db.get('templateEditor', 'lines'), 'lines', 'lineNumbers' );
}
}
},
/**
* Method that updates an editor preference
*
* @param {object} data Event data object from this.menuSelected
* @returns {void}
*/
_changeEditorPreference: function (toValue, type, cmName) {
// Set the menu appropriately
if( toValue ){
$('#elTemplateEditor_preferences_menu')
.find('[data-ipsMenuValue="' + type + '"]').addClass('ipsMenu_itemChecked');
} else {
$('#elTemplateEditor_preferences_menu')
.find('[data-ipsMenuValue="' + type + '"]').removeClass('ipsMenu_itemChecked');
}
// Update controller variable
this._editorPreferences[ type ] = toValue;
// Update local DB
ips.utils.db.set( 'templateEditor', type, toValue );
// Update all CM instances
for( var i in this._cmInstances ){
this._cmInstances[ i ].setOption( cmName, toValue );
}
},
/**
* A dialog has been opened
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
openedDialog: function (e, data) {
if( data.elemID == 'elTemplateEditor_variables' || data.elemID == 'elTemplateEditor_attributes' ){
this._insertVariablesIntoDialog( data );
}
},
/**
* Inserts the current variables value into the dialog
*
* @param {object} data Event data object from the dialog
* @returns {void}
*/
_insertVariablesIntoDialog: function (data) {
// First get the variables
var active = this._getActiveTab();
if( !active.tabPanel ){
return;
}
var variablesValue = $.trim( active.tabPanel.find('[data-role="variables"]').val() );
var descriptionValue = $.trim( active.tabPanel.find('[data-role="description"]').val() );
var titleValue = $.trim( active.tabPanel.find('[data-role="title"]').val() );
var groupValue = $.trim( active.tabPanel.find('[data-role="group"]').val() );
data.dialog
.find('[data-role="variables"]')
.val( variablesValue )
.end()
.find('[data-role="description"]')
.val( descriptionValue )
.end()
.find('[name="_variables_fileid"]')
.val( active.tabPanel.attr('data-fileid') )
.end()
.find('[name="_variables_location"]')
.val( active.tabPanel.attr('data-location') )
.end()
.find('[data-role="title"]')
.val( titleValue );
/* Show the correct select box */
data.dialog.find('select[data-container-type]').addClass('ipsHide');
data.dialog.find('select[data-container-type=' + active.tabPanel.attr('data-location') + ']').removeClass('ipsHide');
data.dialog.find('select[data-container-type=' + active.tabPanel.attr('data-location') + ']').val( groupValue );
/* Reset */
data.dialog.find('#elTemplateEditor_container_title').show();
data.dialog.find('[data-role="container"]').show();
data.dialog.find('[data-role="variables"]').show();
data.dialog.find('#elTemplateEditor_attributes_title').show();
if ( active.tabPanel.attr('data-type') != 'template' )
{
data.dialog.find('#elTemplateEditor_group_title').hide();
data.dialog.find('[data-role="variables"]').hide();
data.dialog.find('#elTemplateEditor_attributes_title').hide();
}
else if ( active.tabPanel.attr('data-location') == 'block')
{
data.dialog.find('#elTemplateEditor_group_title').hide();
data.dialog.find('[data-role="group"]').hide();
}
else if ( active.tabPanel.attr('data-location') == 'database' )
{
/* Can't move */
data.dialog.find('#elTemplateEditor_group_title').hide();
data.dialog.find('[data-role="group"]').hide();
/* Can't rename */
data.dialog.find('#elTemplateEditor_title_title').hide();
data.dialog.find('[data-role="title"]').hide();
}
else if ( active.tabPanel.attr('data-location') == 'page' )
{
/* Hide params */
data.dialog.find('[data-role="variables"]').show();
data.dialog.find('#elTemplateEditor_attributes_title').show();
data.dialog.find('select[data-container-type=' + active.tabPanel.attr('data-location') + ']').show();
}
},
/**
* Updates the value of the variables field in the tab with the given file ID
*
* @param {event} e Event object
* @param {event} e Event data object from templates.variablesDialog
* @returns {void}
*/
updateVariables: function (e, data) {
// Find the panel with the correct fileID, and update it's variables value
this._tabContent
.find('[data-fileid="' + data.fileID + '"]')
.find('[data-role="variables"]')
.val( data.value )
.end()
.find('[data-role="title"]')
.val( data.title )
.end()
.find('[data-role="description"]')
.val( data.description )
.end()
.find('[data-role="group"]')
.val( data.group );
this._updateTabLabel( data.fileID, data.title );
},
/**
* Saves the contents of the editor
*
* @param {event} e Event object
* @returns {void}
*/
save: function (e) {
e.preventDefault();
var self = this;
var active = this._getActiveTab();
var panel = active.tabPanel;
var key = panel.attr('data-fileid');
if( !active.tab || !active.tabPanel ){
Debug.warn('No active tab or tab panel');
return;
}
var save = this._getParametersFromPanel( panel );
// We call .save() on the CodeMirror instance, which will cause it to update the
// contents of the original textbox
this._cmInstances[ key ].save();
// Add it to the save object
save[ 'editor_' + key ] = this.scope.find( '#editor_' + key ).val();
// Name
_.extend( save, {
't_name': panel.find('[data-role="title"]').val()
});
// Description
_.extend( save, {
't_description': panel.find('[data-role="description"]').val()
});
// Group
_.extend( save, {
't_group': panel.find('input[data-role="group"]').val()
});
// If this is a template, add its variables
if( panel.attr('data-location') == 'block' || panel.attr('data-location') == 'database' || panel.attr('data-location') == 'page' ){
_.extend( save, {
't_variables': panel.find('[data-role="variables"]').val()
});
}
// Show loading
this.trigger( 'savingFile.templates' );
// Send it
ips.getAjax()( this._normalURL + '&do=save', {
dataType: 'json',
data: save,
type: 'post'
})
.done( function (response) {
// Let everyone know
self.trigger( 'savedFile.templates', {
key: key,
oldID: parseInt( panel.attr('data-itemID') ),
newID: parseInt( response.template_id ),
newTitle: response.template_title,
oldContainer: parseInt( panel.attr('data-container') ),
newContainer: parseInt( response.template_container ),
status: ( response.template_user_added == 1 ) ? 'custom' : 'changed'
});
// Remove the unsaved status from the tab
self._setChanged( false, key );
// Update the toolbar
self._updateToolbar( active.tab );
// Update the tab name
self._updateTabLabel( key, response.template_title );
})
.fail( function () {
ips.ui.alert.show( {
type: 'alert',
message: ips.getString('saveThemeError'),
icon: 'warn'
});
})
.always( function () {
self.trigger( 'saveFileFinished.templates' );
});
},
/**
* Reverts or deletes a file
* If the bypass parameter is false, this method will confirm the action with the user first
*
* @param {event} e Event object
* @param {boolean} bypass Bypass the user confirmation?
* @returns {void}
*/
revert: function (e, bypass) {
e.preventDefault();
var self = this;
var active = this._getActiveTab();
var panel = active.tabPanel;
var key = panel.attr('data-fileid');
var message = ( $( e.currentTarget ).attr('data-actionType') == 'revert' ) ?
ips.getString('skin_revert_confirm') : ips.getString('skin_delete_confirm');
if( bypass !== true ){
ips.ui.alert.show({
type: 'confirm',
message: message,
icon: 'warn',
callbacks: {
ok: function () {
self.revert( e, true );
}
}
});
return;
}
var save = this._getParametersFromPanel( panel );
// Send it
ips.getAjax()( this._normalURL + '&do=delete', {
dataType: 'json',
data: save,
type: 'post'
})
.done( function (response) {
if( response.template_id ){
self._revertedFile( response, key, active );
} else {
self._deletedFile( key, active );
}
});
},
/**
* Handles updating the editor when a file is reverted
*
* @param {object} response JSON response object from ajax request
* @param {string} key Key of the file that's been reverted
* @param {object} active Object containing keys 'tab' and 'tabPanel' referencing active items
* @returns {void}
*/
_revertedFile: function (response, key, active) {
// Let the document know
this.trigger( 'revertedFile.templates', {
key: key,
oldID: parseInt( active.tabPanel.attr('data-itemID') ),
newID: parseInt( response.template_id ),
status: response.InheritedValue
});
// Update the raw textarea
$( '#editor_' + key ).val( response.template_content );
// Update codemirror
this._cmInstances[ key ].setValue( response.template_content );
// Remove the unsaved status from the tab
this._setChanged( false, key );
// Update the toolbar
this._updateToolbar( active.tab );
},
/**
* Handles updating the editor when a file is deleted
*
* @param {string} key Key of the file that's been reverted
* @param {object} active Object containing keys 'tab' and 'tabPanel' referencing active items
* @returns {void}
*/
_deletedFile: function (key, active) {
this.trigger( 'deletedFile.templates', {
key: key,
fileID: active.tabPanel.attr('data-itemID'),
location: active.tabPanel.attr('data-location'),
type: active.tabPanel.attr('data-type')
});
// Find close link in the tab
active.tab.find('[data-action="closeTab"]').click();
},
/**
* Returns an object of parameters used by the ajax requests
*
* @param {element} panel The panel being used as the source
* @returns {object}
*/
_getParametersFromPanel: function (panel) {
return {
t_type: panel.attr('data-type'),
t_location: panel.attr('data-location'),
t_item_id: panel.attr('data-itemID'),
t_container: panel.find('input[data-role=container]').val(),
t_group: panel.attr('data-group'),
t_name: panel.attr('data-name'),
t_key: panel.attr('data-fileid')
};
},
/**
* A file has been saved or reverted
* Updates the ID of any element with the old ID, and changes the state
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
updateFile: function (e, data) {
this.scope
.find('[data-itemID="' + data.oldID + '"]')
.attr( 'data-itemID', data.newID )
.attr( 'data-container', data.newContainer )
.attr( 'data-inherited-value', data.status );
},
/**
* Event handler for clicking a close tab button
*
* @param {event} e Event object
* @returns {void}
*/
closeTab: function (e) {
var tab = $( e.currentTarget ).closest('.ipsTabs_item');
this._doCloseTab( tab );
},
/**
* Handles closing a tab.
* We first check if the tab is in an 'unsaved' state, and if so, prompt the user to confirm losing changes.
* We then destroy the codemirror instance, remove the tab and panel, and switch to another open tab.
*
* @param {element} tab The tab to be closed
* @param {boolean} bypass Whether to bypass the unsaved check
* @returns {void}
*/
_doCloseTab: function (tab, bypass) {
var self = this;
var tabParent = tab.closest('[data-fileid]');
var key = tabParent.attr('data-fileid');
var allTabs = this._tabBar.find('.ipsTabs_item').closest('[data-fileid]');
var newTab = null;
// Check if there's unsaved content
if( tabParent.attr('data-state') == 'unsaved' && bypass != true ){
ips.ui.alert.show({
type: 'confirm',
message: ips.getString('themeUnsavedContent'),
icon: 'warn',
callbacks: {
ok: function () {
self._doCloseTab( tab, true );
}
}
});
return;
}
// Is this tab active?
var active = tab.hasClass('ipsTabs_activeItem');
// Let the document know what we're up to
this.trigger( 'closedTab.templates', {
fileID: key
});
// Remove the codemirrrrr element & instance
$( this._cmInstances[ key ].getWrapperElement() ).remove();
delete( this._cmInstances[ key ] );
// Find the next or prev tab, if this tab is active, and switch to it
if( active && allTabs.length > 1 ){
if( allTabs.first() == tabParent ){
newTab = tabParent.next();
} else {
newTab = tabParent.prev();
}
}
if( newTab ){
newTab.find('> a').click();
}
// Close the tab
ips.utils.anim.go('fadeOutDown fast', tabParent)
.done( function () {
tabParent.remove();
self._recalculatePanelWrapper();
});
// Remove the panel
this._tabContent.find('[data-fileid="' + key + '"]').remove();
},
/**
* Tab widget has indicated that the user has changed tab
* If there's a file ID, trigger a new event with it, to enable the file listing to highlight it
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
changedTab: function (e, data) {
var tab = data.tab;
if( !_.isUndefined( tab.closest('[data-fileid]').attr('data-fileid') ) ){
this.trigger( 'fileSelected.templates', {
fileID: tab.closest('[data-fileid]').attr('data-fileid')
});
}
this._updateToolbar( tab );
},
/**
* Updates the toolbar buttons
*
* @param {element} tab The current tab
* @returns {void}
*/
_updateToolbar: function (tab) {
var tabParent = tab.closest('[data-fileid]').attr('data-fileid');
var tabPanel = this._tabContent.find('[data-fileid="' + tabParent + '"]');
var status = tabPanel.attr('data-inherited-value');
var type = tabPanel.attr('data-type');
var revert = this.scope.find('[data-action="revert"]');
switch( status ){
case 'original':
case 'inherit':
revert
.addClass('ipsButton_disabled')
break;
case 'custom':
revert
.html( ips.getString('skin_delete') )
.removeClass('ipsButton_disabled')
.attr('data-actionType', 'delete')
.show();
break;
case 'changed':
revert
.html( ips.getString('skin_revert') )
.removeClass('ipsButton_disabled')
.attr('data-actionType', 'revert')
.show();
break;
}
$('#elTemplateEditor_variables').show();
$('#elTemplateEditor_attributes').hide();
},
/**
* Reponds to the openFile event, to open a file
* Either switch to it if already open, or hand off to _buildTab to load it
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
openFile: function (e, data) {
// Is this file already open?
if( !this._tabBar.find('[data-fileid="' + data.meta.key + '"]').length ){
this._buildTab( data.meta );
} else {
this._tabBar.find('[data-fileid="' + data.meta.key + '"] > a').click();
}
},
/**
* Builds a tab for the file with the given metadata
*
* @param {object} meta Object of file metadata
* @returns {void}
*/
_buildTab: function (meta) {
var self = this;
this._tabContent.attr('data-haseditor', 'true');
this.scope.find('#elTemplateEditor_panels_empty').hide();
// Build the actual tab
this._tabBar.append( ips.templates.render('templates.editor.newTab', {
title: meta.title,
fileid: meta.key,
location: meta.location,
group: meta.group,
container: meta.container,
id: 'tab_' + meta.key
}));
// Build the content container
this._tabContent.append( ips.templates.render('templates.editor.tabPanel', {
fileid: meta.key,
name: meta.name,
type: meta.type,
location: meta.location,
container: meta.container,
group: meta.group,
id: meta.id,
inherited: meta.inherited
}));
// We may need to rejig the tab pane wrap to account for wrapped tabs,
// so do that now both tab and panel have been added
this._recalculatePanelWrapper();
// Toggle the new tab
this._tabBar.find('[data-fileid="' + meta.key + '"] > a').click();
// Manually set the content area to loading since we aren't using ui.tabbar's load methods
this._tabContent.addClass('ipsLoading ipsTabs_loadingContent');
// Load the content
ips.getAjax()( this._ajaxURL + '&do=loadTemplate&show=json', {
dataType: 'json',
data: {
't_container': meta.container,
't_group': meta.group,
't_name': meta.name,
't_key': meta.key,
't_location': meta.location,
't_type': meta.type
}
})
.done( function (response) {
self._postProcessNewTab( response, meta );
})
.always( function () {
self._tabContent.removeClass('ipsLoading ipsTabs_loadingContent');
});
},
/**
* Update the tab label
*
* @param {string} key File key (block__foo)
* @param {string} title Label Title (Foo)
* @return {void}
*/
_updateTabLabel: function( key, title )
{
var span = this._tabBar.find('[data-fileid="' + key + '"] > a span').clone();
this._tabBar.find('[data-fileid="' + key + '"] > a').html( title ).append( span );
},
/**
* Once tab content has been returned by ajax, this method builds the content of a tab,
* and initializes codemirrior for syntax highlighting
*
* @param {object} response Response JSON object from ajax request
* @param {object} meta Object of meta data for the tab being created
* @returns {void}
*/
_postProcessNewTab: function (response, meta) {
var content = ips.templates.render('templates.editor.tabContent', {
fileid: meta.key,
content: response.template_content,
variables: response.template_params,
description: response.template_desc,
title: response.template_title,
container: response.template_container,
group: response.template_group
});
this._tabContent.find('[data-fileid="' + meta.key + '"]').html( content );
this._initCodeMirror( meta.key, meta.type );
},
/**
* Initializes CodeMirror on a textarea with the provided key
*
* @param {string} key Key of the textarea to be turned into codemirrior
* @returns {void}
*/
_initCodeMirror: function (key, type) {
var self = this;
this._cmInstances[ key ] = CodeMirror.fromTextArea( document.getElementById('editor_' + key ), {
mode: (type == 'template' ? 'htmlmixed' : 'css'),
lineWrapping: this._editorPreferences['wrap'],
lineNumbers: this._editorPreferences['lines']
} );
this._cmInstances[ key ].setSize( null, this._getTabContentHeight() );
this._cmInstances[ key ].on( 'change', function (doc, cm) {
self._setChanged( true, key );
});
},
/**
* Sets a tab to 'unsaved' state
*
* @returns {void}
*/
_setChanged: function (state, key) {
if( state == true ){
// Update 'x' in tab to an unsaved version, then set state on the tab
this._tabBar
.find('[data-fileid="' + key + '"]')
.attr('data-state', 'unsaved')
.find('[data-action="closeTab"]')
.html( ips.templates.render('templates.editor.unsaved') );
} else {
this._tabBar
.find('[data-fileid="' + key + '"]')
.attr('data-state', 'saved')
.find('[data-action="closeTab"]')
.html( ips.templates.render('templates.editor.saved') );
}
},
/**
* Calculates whether the tab bar has wrapped, and if so, resizes the panel wrapper and updates
* CodeMirror instances with the new height
*
* @returns {void}
*/
_recalculatePanelWrapper: function () {
// Get height of the tab bar
var tabHeight = this._tabBar.outerHeight();
if( tabHeight == this._currentHeight ){
return;
}
// Set the top value of the panel
this._tabContent.css( { top: tabHeight + 'px' } );
// Get the height of it
var contentHeight = this._getTabContentHeight();
// Find all codemirror instances and resize those
this._tabContent.find('.CodeMirror').css( { height: contentHeight + 'px' } );
this._currentHeight = tabHeight;
},
/**
* Returns references to both the active tab and the active tab panel
*
* @returns {object} Contains keys 'tab' and 'tabPanel', which are jQuery objects
*/
_getActiveTab: function () {
var toReturn = {
tab: null,
tabPanel: null
};
var tab = this._tabBar.find('.ipsTabs_item.ipsTabs_activeItem').first().parent();
if( !tab.length ){
return toReturn;
}
// Get the associated panel
toReturn = {
tab: tab,
tabPanel: this._tabContent.find('[data-fileid="' + tab.attr('data-fileid') + '"]')
};
return toReturn;
},
/**
* Returns the current height of the tab panel wrapper
*
* @returns {number}
*/
_getTabContentHeight: function () {
return this._tabContent.outerHeight();
}
});
}(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.fileList.js" javascript_type="controller" javascript_version="100045" javascript_position="1000250"><![CDATA[/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.templates.fileList.js - Templates: controller for the file listing component of the template manager
*
* Author: Rikki Tissier
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('cms.admin.templates.fileList', {
_tabBar: null,
_tabContent: null,
initialize: function () {
// Events started here
this.on( 'click', '[data-action="openFile"]', this.openFile );
this.on( 'click', '[data-action="toggleBranch"]', this.toggleBranch );
this.on( 'modifiedFile.templates', this.refreshFileList );
// Events coming from elsewhere
this.on( document, 'fileSelected.templates', this.selectFile );
this.on( document, 'savedFile.templates revertedFile.templates', this.updateItemMeta );
this.on( document, 'savedFile.templates revertedFile.templates', this.fileChangedStatus );
this.on( document, 'addedFile.templates', this.refreshFileList );
this.on( document, 'deletedFile.templates', this.refreshFileList );
// Other setup
this.setup();
},
/**
* Setup method
*
* @returns {void}
*/
setup: function () {
this._tabBar = this.scope.find('#elTemplateEditor_typeTabs');
this._tabContent = this.scope.find('#elTemplateEditor_fileList');
},
/**
* Something has changed in the file list, so we refresh it and try and remember
* the position we were at. If a new file ID is provided, we'll also select it.
*
* @param {event} e Event object
* @returns {void}
*/
refreshFileList: function (e, data) {
var self = this;
var type = data.type;
var panel = this._tabContent.find('.cTemplateList[data-type="' + type + '"]');
var activeItem = panel.find('.cTemplateList_activeNode > a').attr('data-key');
// If the panel isn't actually open, we'll just show it
if( !panel.length ){
this._tabBar.find('[data-type="' + type + '"]').click();
} else {
var open = this._getOpenNodes( panel );
// Now fetch the new list
var url = this._tabBar.find('[data-type]').attr('data-tabURL');
ips.getAjax()( url )
.done( function (response) {
panel.html( response );
// Now reopen all the nodes
self._openNodes( open, panel, activeItem );
if( data.fileID ){
// Click it
panel.find('[data-itemid="' + data.fileID + '"]').click();
}
// Let everyone know
self.trigger('fileListRefreshed.templates');
});
}
},
/**
* Opens the nodes provided in the toOpen param
*
* @param {object} toOpen Object of nodes to open, containing three keys: apps, locations, groups
* @returns {void}
*/
_openNodes: function (toOpen, panel, activeItem) {
var selector = [];
// Get the locations
if( toOpen.locations.length ){
for( var i = 0; i < toOpen.locations.length; i++ ){
selector.push('[data-location="' + toOpen.locations[i] + '"]');
}
}
// Get groups
if( toOpen.groups.length ){
for( var i = 0; i < toOpen.groups.length; i++ ){
var str = '[data-location="' + toOpen.groups[i][0] + '"] ';
str += '[data-group="' + toOpen.groups[i][1] + '"]';
selector.push( str );
}
}
// Now close all branches, then reopen the ones matching our selector
panel
.find('.cTemplateList_activeBranch')
.removeClass('cTemplateList_activeBranch')
.addClass('cTemplateList_inactiveBranch')
.end()
.find( selector.join(',') )
.removeClass('cTemplateList_inactiveBranch')
.addClass('cTemplateList_activeBranch');
// Anything to make active?
if( activeItem ){
panel
.find('[data-key="' + activeItem + '"]')
.click();
}
},
/**
* Returns an object containing the open nodes in the provided panel
*
* @param {element} panel Panel element to fetch from
* @returns {object} Three array keys: apps, locations, groups
*/
_getOpenNodes: function (panel) {
var locations = [];
var groups = [];
// Fetch all open nodes
panel.find('.cTemplateList_activeBranch').each( function (i, item) {
var el = $( item );
if( el.attr('data-location') ){
locations.push( el.attr('data-location') );
}
if( el.attr('data-group') ){
groups.push( [
el.closest('[data-location]').attr('data-location'),
el.attr('data-group')
]);
}
});
return {
locations: locations,
groups: groups
};
},
/**
* The editor controller has indicated that a file tab has been selected
* We respond to this event by highlighting the file in the list
*
* @param {event} e Event object
* @returns {void}
*/
selectFile: function (e, data) {
if( data.fileID ){
this._makeActive( data.fileID );
}
},
/**
* Event handler for clicking a file node in the listing.
* Gather metadata from the file, then trigger an event so that the editor controller
* can load it.
*
* @param {event} e Event object
* @returns {void}
*/
openFile: function (e) {
e.preventDefault();
var elem = $( e.currentTarget );
// Get meta data for this file
var meta = {
name: elem.attr('data-name'),
key: elem.attr('data-key'),
type: elem.closest('[data-type]').attr('data-type'),
title: elem.text(),
group: elem.closest('[data-group]').attr('data-group'),
location: elem.closest('[data-location]').attr('data-location'),
id: elem.closest('[data-itemID]').attr('data-itemID'),
inherited: elem.closest('[data-inherited-value]').attr('data-inherited-value')
};
Debug.log( meta );
this.trigger( 'openFile.templates', {
meta: meta
});
},
/**
* Event handler for clicking a branch in the listing.
* Expends or collapses the branch
*
* @param {event} e Event object
* @returns {void}
*/
toggleBranch: function (e) {
e.preventDefault();
var branchTrigger = $( e.currentTarget );
var branchItem = branchTrigger.parent();
if( branchItem.hasClass('cTemplateList_inactiveBranch') ){
ips.utils.anim.go( 'fadeInDown', branchItem.find(' > ul') );
branchItem
.removeClass('cTemplateList_inactiveBranch')
.addClass('cTemplateList_activeBranch');
} else {
branchItem.find(' > ul').hide();
branchItem
.removeClass('cTemplateList_activeBranch')
.addClass('cTemplateList_inactiveBranch');
}
},
/**
* Updates the ID of any element with the old ID
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
updateItemMeta: function (e, data) {
if( data.oldID != data.newID ){
this.scope
.find('[data-itemID="' + data.oldID + '"]')
.attr( 'data-itemID', data.newID );
}
/* Update name */
this.scope
.find('[data-itemID="' + data.newID + '"]')
.attr( 'data-name', data.newTitle )
.html( data.newTitle );
/* Update container */
if ( data.oldContainer != data.newContainer )
{
data.fileID = data.newID;
// Let everyone know
this.trigger( 'modifiedFile.templates', data );
}
},
/**
* A file's status has changed, so we update it with the new status
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
fileChangedStatus: function (e, data) {
this.scope
.find('[data-key="' + data.key + '"]')
.attr( 'data-inherited-value', data.status );
},
/**
* Finds the provided fileID in the list, highlights it and opens all branches to it
*
* @param {string} fileID fileID of node to higlight
* @returns {void}
*/
_makeActive: function (fileID) {
// Find the file entry
var file = this.scope.find('[data-key="' + fileID +'"]');
// Make all others inactive
this.scope.find('[data-key]').parent().removeClass('cTemplateList_activeNode');
// Make this one active
file.parent().addClass('cTemplateList_activeNode');
// Get all parent nodes, and show them
file.parents('li[data-group], li[data-location]').each( function (idx, parent) {
if( $( parent ).hasClass('cTemplateList_inactiveBranch') ){
$( parent )
.removeClass('cTemplateList_inactiveBranch')
.addClass('cTemplateList_activeBranch')
.find('> ul')
.show();
}
});
},
/**
* Returns the currently-selected type being shown (templates or css)
*
* @returns {string}
*/
_currentType: function () {
if( this._tabBar.find('[data-type="template"]').hasClass('ipsTabs_activeItem') ){
return 'template';
}
if( this._tabBar.find('[data-type="js"]').hasClass('ipsTabs_activeItem') ){
return 'js';
}
return 'css';
}
});
}(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.main.js" javascript_type="controller" javascript_version="100045" javascript_position="1000250">/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.templates.main.js - Templates: Parent controller for the template editor
* Simply manages showing the loading thingy based on events coming from within
*
* Author: Rikki Tissier
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('cms.admin.templates.main', {
initialize: function () {
this.on( 'savingFile.templates', this.showLoading );
this.on( 'saveFileFinished.templates', this.hideLoading );
},
/**
* Shows the loading thingy
*
* @param {event} e Event object
* @returns {void}
*/
showLoading: function (e) {
ips.utils.anim.go( 'fadeIn', this.scope.find('[data-role=&quot;loading&quot;]') );
},
/**
* Hides the loading thingy
*
* @param {event} e Event object
* @returns {void}
*/
hideLoading: function (e) {
ips.utils.anim.go( 'fadeOut', this.scope.find('[data-role=&quot;loading&quot;]') );
}
});
}(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.variablesDialog.js" javascript_type="controller" javascript_version="100045" javascript_position="1000250">/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.templates.variablesDialog.js - Controller for the variables dialog
*
* Author: Rikki Tissier
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('cms.admin.templates.variablesDialog', {
initialize: function () {
this.on( 'click', 'input[type=&quot;submit&quot;]', this.submitChange );
},
/**
* Event handler called when the submit button within the dialog is clicked
* Fires an event that the editor controller can respond to
*
* @param {event} e Event object
* @returns {void}
*/
submitChange: function (e) {
this.trigger( 'variablesUpdated.templates', {
fileID: this.scope.find('[name=&quot;_variables_fileid&quot;]').val(),
value: this.scope.find('[data-role=&quot;variables&quot;]').val(),
title: this.scope.find('[data-role=&quot;title&quot;]').val(),
description: this.scope.find('[data-role=&quot;description&quot;]').val(),
container: this.scope.find('[data-role=&quot;container&quot;]').val(),
group: this.scope.find('[data-role=&quot;group&quot;]:not(.ipsHide)').val()
});
this.trigger( 'closeDialog' );
}
});
}(jQuery, _));</file>
<file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.builder.area.js" javascript_type="mixins" javascript_version="100045" javascript_position="1000100"><![CDATA[/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.cms.builder.area.js - Front-end mixin for tables
*
* Author: Matt Mecham
*/
;( function($, _, undefined){
"use strict";
ips.controller.mixin('builder.area', 'core.front.widgets.area', true, function () {
_pageID: null;
/**
* After init, init
*
* @returns {void}
*/
this.after('setup', function () {
});
/**
* Updates the ordering of widgets in this area
*
* @returns {void}
*/
this.updateOrdering = function (without) {
var body = $('body');
var order = this.scope.find('> ul').sortable('toArray', {
attribute: 'data-blockID'
});
order = ( without ) ? _.without( _.uniq( order ), without ) : _.uniq( order );
// Remove hidden blocks as these should not be stored
var self = this;
_.each( order, function( value, key )
{
if ( self.scope.find('li[data-blockID=' + value + ']').attr('data-hidden') == 'true' )
{
order = _.without( order, value );
}
} );
ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=cms&module=pages&controller=builder&do=saveOrder&orientation=' + this._orientation, {
data: {
order: order,
pageID: $('#elCmsPageWrap').attr('data-pageid'),
area: this._areaID
}
})
.fail( function () {
ips.ui.alert.show( {
type: 'alert',
icon: 'warn',
message: ips.getString('sidebarError'),
callbacks: {}
});
});
};
});
}(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.builder.block.js" javascript_type="mixins" javascript_version="100045" javascript_position="1000100"><![CDATA[/**
* IPS Social Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
*
* ips.cms.builder.block.js - Front-end mixin for CMS sidebar
*
* Author: Matt Mecham
*/
;( function($, _, undefined){
"use strict";
ips.controller.mixin('builder.block', 'core.front.widgets.block', true, function () {
/**
* When the menu is opened, we need to load the form into it
*
* @returns {void}
*/
this.menuOpened = function (e, data) {
/* Don't override menus inside the block */
if ( ! this.scope.closest('[data-widgetArea]').hasClass('cWidgetContainer_managing') )
{
return;
}
var body = $('body');
var area = this.scope.closest('[data-widgetArea]').attr('data-widgetArea');
var block = this._blockID;
var self = this;
var managerBlock = $('[data-role="availableBlocks"] [data-blockID="' + this._getBlockIDWithoutUniqueKey( this._blockID ) + '"]');
var menuStyle = managerBlock.attr('data-menuStyle');
if ( menuStyle == 'modal' )
{
var dialogRef = ips.ui.dialog.create({
title: managerBlock.find('h4').html(),
url: ips.getSetting('baseURL') + 'index.php?app=cms&module=pages&controller=builder&do=getConfiguration&block=' + block + '&pageID=' + $('#elCmsPageWrap').attr('data-pageid') + '&pageArea=' + area,
forceReload: true,
remoteSubmit: true
});
dialogRef.show();
Debug.log( dialogRef );
$('#' + dialogRef.dialogID ).css( "height", "1000px");
this._modalOpen = block;
}
else
{
data.menu.html( $('<div/>').addClass('ipsLoading').css({ height: '100px' }) );
setTimeout( function () {
ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=cms&module=pages&controller=builder&do=getConfiguration', {
data: {
block: block,
pageID: $('#elCmsPageWrap').attr('data-pageid'),
pageArea: area
}
} )
.done( function (response) {
data.menu
.html( response )
.find('form')
.on( 'submit', _.bind( self._configurationForm, self, data.menu ) );
});
}, 1000);
}
};
/**
* Event handler/method that reloads the entire contents of this widget
*
* @returns {void}
*/
this.reloadContent = function () {
var self = this;
this._setLoading( true );
// Get content
if( this._ajaxObj && this._ajaxObj.abort ){
this._ajaxObj.abort();
}
var body = $('body');
var url = ips.getSetting('baseURL') + 'index.php?app=cms&module=pages&controller=builder&do=getBlock&blockID=' + this._blockID + '&pageID=' + $('#elCmsPageWrap').attr('data-pageid') + '&orientation=' + this._orientation;
this._ajaxObj = ips.getAjax()( url )
.done( function (response) {
self.scope.hide().html( response );
ips.utils.anim.go('fadeIn', self.scope);
self.trigger('loadedWidget.widgets', {
blockID: self._blockID
});
})
.fail( function () {
self.scope.html('Error');
})
.always( function () {
self._setLoading( false );
});
};
});
}(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="templates" javascript_name="ips.templates.templates.js" javascript_type="template" javascript_version="100045" javascript_position="1000250"><![CDATA[/* TEMPLATE EDITOR TEMPLATES */
/* TEMPLATECEPTION */
ips.templates.set('templates.editor.newTab', " \
<li data-fileid='{{fileid}}' data-location='{{location}}'>\
<a href='#' class='ipsTabs_item' id='{{id}}'>{{title}} <span data-action='closeTab'><i class='fa fa-times'></i></span></a>\
</li>\
");
ips.templates.set('templates.editor.tabPanel', " \
<div data-fileid='{{fileid}}' id='ipsTabs_elTemplateEditor_tabbar_tab_{{fileid}}_panel' class='ipsTabs_panel' style='display: none' data-location='{{location}}' data-type='{{type}}' data-group='{{group}}' data-name='{{name}}' data-type='{{type}}' data-itemID='{{id}}' data-inherited-value='{{inherited}}'>\
{{{content}}}\
</div>\
");
ips.templates.set('templates.editor.tabContent', " \
<input data-role='group' type='hidden' name='group_{{fileid}}' value=\"{{{group}}}\">\
<input data-role='variables' type='hidden' name='variables_{{fileid}}' value=\"{{{variables}}}\">\
<input data-role='title' type='hidden' name='title_{{fileid}}' value=\"{{{title}}}\">\
<input data-role='description' type='hidden' name='description_{{fileid}}' value=\"{{{description}}}\">\
<textarea data-fileid='{{fileid}}' id='editor_{{fileid}}'>{{{content}}}</textarea>\
");
ips.templates.set('templates.editor.unsaved', " \
<i class='fa fa-circle'></i>\
");
ips.templates.set('templates.editor.saved', " \
<i class='fa fa-times'></i>\
");]]></file>
<order app="global" path="/dev/js//framework/">templates
common/ui
common/utils
common
controllers</order>
<order app="global" path="/dev/js//library/">underscore
jquery
mustache
jstz
Debug.js
app.js</order>
<order app="global" path="/dev/js//library//jquery">jquery.js
jquery.history.js
jquery.transform.js</order>
<order app="global" path="/dev/js//library//xregexp">xregexp-all.js
xregexp-lookbehind.js</order>
</javascript>