winter/modules/cms/assets/js/october.cmspage.js

596 lines
23 KiB
JavaScript

/*
* Scripts for the CMS page.
*/
+function ($) { "use strict";
$(document).ready(function(){
/*
* Listen for the "open.oc.list" event in the template lists
*/
$(document).on('open.oc.list', '#cms-side-panel', function(e) {
var
$item = $(e.relatedTarget),
$form = $item.closest('[data-template-type]'),
data = {
type: $form.data('template-type'),
theme: $item.data('item-theme'),
path: $item.data('item-path')
},
tabId = data.type + '-' + data.theme + '-' + data.path
if (data.type == 'asset' && $item.data('editable') === undefined)
return true
if ($form.length == 0)
return false
/*
* Find if the tab is already opened
*/
if ($('#cms-master-tabs').data('oc.tab').goTo(tabId))
return false
/*
* Open a new tab
*/
$.oc.stripeLoadIndicator.show()
$form.request('onOpenTemplate', {
data: data,
success: function(data) {
this.success(data).done(function(){
$.oc.stripeLoadIndicator.hide()
$('#cms-master-tabs').ocTab('addTab', data.title, data.tab, tabId, $form.data('type-icon'))
}).always(function(){
$.oc.stripeLoadIndicator.hide()
})
},
error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.responseText.length ? jqXHR.responseText : jqXHR.statusText)
$.oc.stripeLoadIndicator.hide()
}
})
return false
})
/*
* Detect invalid fields, uncollapse the panel
*/
$(window).on('ajaxInvalidField', function(ev, element, name){
var $panel = element.closest('.form-tabless-fields.collapsed'),
$primaryPanel = element.closest('.control-tabs.primary.collapsed')
if ($panel.length > 0)
$panel.removeClass('collapsed')
if ($primaryPanel.length > 0) {
$primaryPanel.removeClass('collapsed')
var pane = $primaryPanel.closest('.tab-pane'),
$secondaryPanel = $('.control-tabs.secondary', pane)
$secondaryPanel.removeClass('primary-collapsed')
}
element.focus()
})
/*
* Listen for the closed event
*/
$('#cms-master-tabs').on('closed.oc.tab', function(event){
updateModifiedCounter()
})
/*
* Listen for the tabs "shown" event to track the current template in the list
*/
$('#cms-master-tabs').on('shown.bs.tab', function(event){
if ($(event.target).closest('[data-control=tab]').attr('id') != 'cms-master-tabs')
return
var dataId = $(event.target).closest('li').attr('data-tab-id')
$('#cms-side-panel [data-control=filelist]').fileList('markActive', dataId)
$('#cms-side-panel form').trigger('oc.list.setActiveItem', [dataId])
})
/*
* Listen for the tabs "initTab" event to inject extra controls to the tab
*/
$('#cms-master-tabs').on('initTab.oc.tab', function(event, data){
if ($(event.target).attr('id') != 'cms-master-tabs')
return
var $collapseIcon = $('<a href="javascript:;" class="tab-collapse-icon tabless"><i class="icon-chevron-up"></i></a>')
var $panel = $('.form-tabless-fields', data.pane)
$panel.append($collapseIcon);
$collapseIcon.click(function(){
$panel.toggleClass('collapsed')
if (typeof(localStorage) !== 'undefined')
localStorage.ocCmsTablessCollapsed = $panel.hasClass('collapsed') ? 1 : 0
window.setTimeout(function(){
$(window).trigger('oc.updateUi')
}, 500)
return false
})
var $primaryCollapseIcon = $('<a href="javascript:;" class="tab-collapse-icon primary"><i class="icon-chevron-down"></i></a>')
var $primaryPanel = $('.control-tabs.primary', data.pane)
var $secondaryPanel = $('.control-tabs.secondary', data.pane)
if ($primaryPanel.length > 0) {
$secondaryPanel.append($primaryCollapseIcon);
$primaryCollapseIcon.click(function(){
$primaryPanel.toggleClass('collapsed')
$secondaryPanel.toggleClass('primary-collapsed')
$(window).trigger('oc.updateUi')
if (typeof(localStorage) !== 'undefined')
localStorage.ocCmsPrimaryCollapsed = $primaryPanel.hasClass('collapsed') ? 1 : 0
return false
})
}
if (typeof(localStorage) !== 'undefined') {
if (!$('a', data.tab).hasClass('new-template') && localStorage.ocCmsTablessCollapsed == 1)
$panel.addClass('collapsed')
if (localStorage.ocCmsPrimaryCollapsed == 1) {
$primaryPanel.addClass('collapsed')
$secondaryPanel.addClass('primary-collapsed')
}
}
var $componentListFormGroup = $('.control-componentlist', data.pane).closest('.form-group')
if ($primaryPanel.length > 0)
$primaryPanel.before($componentListFormGroup)
else
$secondaryPanel.parent().before($componentListFormGroup)
$componentListFormGroup.removeClass()
$componentListFormGroup.addClass('layout-row min-size')
updateComponentListClass(data.pane)
updateFormEditorMode(data.pane, true)
var $form = $('form', data.pane)
$form.on('changed.oc.changeMonitor', function() {
$panel.trigger('modified.oc.tab')
updateModifiedCounter()
})
$form.on('unchanged.oc.changeMonitor', function() {
$panel.trigger('unmodified.oc.tab')
updateModifiedCounter()
})
})
/*
* Listen for the "afterAllClosed.oc.tab" event in the master tabs widget
*/
$('#cms-master-tabs').on('afterAllClosed.oc.tab', function(event){
$('#cms-side-panel [data-control=filelist]').fileList('markActive', null)
$('#cms-side-panel form').trigger('oc.list.setActiveItem', [null])
})
/*
* Listen for AJAX updates of the list views
*/
$(document).on('ajaxUpdate', '[data-control=filelist], [data-control=assetlist]', function(event){
var dataId = $('#cms-master-tabs .nav-tabs li.active').attr('data-tab-id')
$('#cms-side-panel [data-control=filelist]').fileList('markActive', dataId)
$('#cms-side-panel form').trigger('oc.list.setActiveItem', [dataId])
})
/*
* Listen for the template forms AJAX success event
*/
$(document).on('ajaxSuccess', '#cms-master-tabs form', function(event, context, data){
if (data.templatePath !== undefined) {
$('input[name=templatePath]', this).val(data.templatePath)
$('input[name=templateMtime]', this).val(data.templateMtime)
$('[data-control=delete-button]', this).removeClass('hide')
$('[data-control=preview-button]', this).removeClass('hide')
if (data.pageUrl !== undefined)
$('[data-control=preview-button]', this).attr('href', data.pageUrl)
}
if (data.title !== undefined)
$('#cms-master-tabs').ocTab('updateTitle', $(this).closest('.tab-pane'), data.title)
var tabId = $('input[name=templateType]', this).val() + '-'
+ $('input[name=theme]', this).val() + '-'
+ $('input[name=templatePath]', this).val();
$('#cms-master-tabs').ocTab('updateIdentifier', $(this).closest('.tab-pane'), tabId)
var templateType = $('input[name=templateType]', this).val()
if (templateType.length > 0) {
$.oc.cmsPage.updateTemplateList(templateType)
if (templateType == 'layout')
updateLayouts(this)
}
updateFormEditorMode($(this).closest('.tab-pane'), false)
if (context.handler == 'onSave' && (!data['X_OCTOBER_ERROR_FIELDS'] && !data['X_OCTOBER_ERROR_MESSAGE'])) {
$(this).trigger('unchange.oc.changeMonitor')
}
})
$(document).on('ajaxError', '#cms-master-tabs form', function(event, context, data, jqXHR){
if (context.handler == 'onSave') {
if (jqXHR.responseText == 'mtime-mismatch') {
event.preventDefault()
handleMtimeMismatch(this)
}
}
})
/*
* Listen for the oc.createTemplate event
*/
$(document).on('click', '#cms-side-panel form button[data-control=create-template], #cms-side-panel form li a[data-control=create-template]', function(event){
var
$form = $(this).closest('[data-template-type]'),
type = $form.data('template-type'),
tabId = type + Math.random()
$.oc.stripeLoadIndicator.show()
$form.request('onCreateTemplate', {
data: {
type: type
},
success: function(data) {
this.success(data).done(function(){
$('#cms-master-tabs').ocTab('addTab', data.title, data.tab, tabId, $form.data('type-icon') + ' new-template')
$('#layout-side-panel').trigger('close.oc.sidePanel')
}).always(function(){
$.oc.stripeLoadIndicator.hide()
})
}
})
})
/*
* Listen for the oc.deleteTemplate event
*/
$(document).on('click', '#cms-side-panel form button[data-control=delete-template]', function(event){
var
$el = $(this),
$form = $el.closest('form'),
templateType = $form.data('template-type')
if (!confirm($el.data('confirmation')))
return
$form.request('onDeleteTemplates', {
data: {
type: templateType
},
success: function(data) {
var tabs = $('#cms-master-tabs').data('oc.tab');
$.each(data.deleted, function(index, path){
var
tabId = templateType + '-' + data.theme + '-' + path,
tab = tabs.findByIdentifier(tabId)
$('#cms-master-tabs').ocTab('closeTab', tab, true)
})
if (data.error !== undefined && $.type(data.error) === 'string' && data.error.length)
$.oc.flashMsg({text: data.error, 'class': 'error'})
},
complete: function() {
$.oc.cmsPage.updateTemplateList(templateType)
}
})
})
/*
* Listen for the showing.oc.inspector event on the components
*/
$(document).on('showing.oc.inspector', '[data-inspectable]', function(ev, data) {
$(ev.currentTarget).closest('[data-control="toolbar"]').data('oc.dragScroll').goToElement(ev.currentTarget, data.callback)
ev.stopPropagation()
})
/*
* Listen for the hidden.oc.inspector event on the components
*/
$(document).on('hidden.oc.inspector', '[data-inspectable]', function() {
var values = $.parseJSON($('[data-inspector-values]', this).val())
$('[name="component_aliases[]"]', this).val(values['oc.alias'])
$('span.alias', this).text(values['oc.alias'])
})
/*
* Listen for the hiding.oc.inspector event on the components
*/
$(document).on('hiding.oc.inspector', '[data-inspectable]', function(e, values) {
var values = $.parseJSON($('[data-inspector-values]', this).val()),
alias = values['oc.alias'],
$componentList = $('#cms-master-tabs > div.tab-content > .tab-pane.active .control-componentlist .layout'),
$cell = $(e.target).parent()
$('div.layout-cell', $componentList).each(function(){
if ($cell.get(0) == this)
return true
var $input = $('input[name="component_aliases[]"]', this)
if ($input.val() == alias) {
e.preventDefault()
alert('The component alias "'+alias+'" is already used.')
return false
}
})
})
function updateComponentListClass(pane) {
var $componentList = $('.control-componentlist', pane)
$componentList.toggleClass('has-components', $('.layout', $componentList).children().length > 0)
}
function updateFormEditorMode(pane, initialization) {
var $contentTypeElement = $('[data-toolbar-type]', pane)
if ($contentTypeElement.length == 0)
return
if ($contentTypeElement.data('toolbar-type') != 'content')
return
var fileName = $('input[name=fileName]', pane).val(),
parts = fileName.split('.'),
extension = 'txt',
mode = 'plain_text',
modes = {
'htm': 'html',
'md': 'markdown',
'txt': 'plain_text',
'js': 'javascript',
'less': 'less',
'scss': 'scss',
'sass': 'sass',
'css': 'css'
},
editor = $('[data-control=codeeditor]', pane)
if (parts.length >= 2)
extension = parts.pop().toLowerCase()
if (modes[extension] !== undefined)
mode = modes[extension];
var setEditorMode = function() {
window.setTimeout(function(){
editor.data('oc.codeEditor').editor.getSession().setMode({path: 'ace/mode/'+mode})
}, 200)
}
if (initialization)
editor.on('oc.codeEditorReady', setEditorMode)
else
setEditorMode()
}
function updateModifiedCounter() {
var counters = {
page: {menu: 'pages', count: 0},
partial: {menu: 'partials', count: 0},
layout: {menu: 'layouts', count: 0},
content: {menu: 'content', count: 0},
asset:{menu: 'assets', count: 0}
}
$('> div.tab-content > div.tab-pane[data-modified]', '#cms-master-tabs').each(function(){
var inputType = $('> form > input[name=templateType]', this).val()
counters[inputType].count++
})
$.each(counters, function(type, data){
$.oc.sideNav.setCounter('cms/' + data.menu, data.count);
})
}
function handleMtimeMismatch(form) {
var $form = $(form)
$form.popup({ handler: 'onOpenConcurrencyResolveForm' })
var popup = $form.data('oc.popup')
$(popup.$target).on('click', 'button[data-action=reload]', function(){
popup.hide()
reloadForm(form)
})
$(popup.$target).on('click', 'button[data-action=save]', function(){
popup.hide()
$('input[name=templateForceSave]', $form).val(1)
$('a[data-request=onSave]', $form).trigger('click')
$('input[name=templateForceSave]', $form).val(0)
})
}
function reloadForm(form) {
var
$form = $(form),
data = {
type: $('[name=templateType]', $form).val(),
theme: $('[name=theme]', $form).val(),
path: $('[name=templatePath]', $form).val(),
},
tabId = data.type + '-' + data.theme + '-' + data.path,
tabs = $('#cms-master-tabs').data('oc.tab'),
tab = tabs.findByIdentifier(tabId)
/*
* Update tab
*/
$.oc.stripeLoadIndicator.show()
$form.request('onOpenTemplate', {
data: data,
success: function(data) {
this.success(data).done(function(){
$.oc.stripeLoadIndicator.hide()
$('#cms-master-tabs').ocTab('updateTab', tab, data.title, data.tab)
$('#cms-master-tabs').ocTab('unmodifyTab', tab)
updateModifiedCounter()
}).always(function(){
$.oc.stripeLoadIndicator.hide()
})
},
error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.responseText.length ? jqXHR.responseText : jqXHR.statusText)
$.oc.stripeLoadIndicator.hide()
}
})
}
/*
* Listen for the click event on the components' remove link
*/
$(document).on('click', '#cms-master-tabs > div.tab-content > .tab-pane.active .control-componentlist a.remove', function(e) {
$(this).trigger('change')
var pane = $(this).closest('.tab-pane'),
component = $(this).closest('div.layout-cell')
/*
* Remove any {% component %} tags in the editor for this component
*/
var editor = $('[data-control=codeeditor]', pane)
if (editor.length) {
var alias = $('input[name="component_aliases[]"]', component).val(),
codeEditor = editor.codeEditor('getEditorObject')
codeEditor.replace('', {
needle: "{% component '" + alias + "' %}"
})
}
component.remove()
$(window).trigger('oc.updateUi')
updateComponentListClass(pane)
return false
})
/*
* Listen for the click event in the component list
*/
$(document).on('click', '#cms-component-list [data-component]', function(e) {
/*
* Determine if a page or layout is open in the master tabs
*/
var $componentList = $('#cms-master-tabs > div.tab-content > .tab-pane.active .control-componentlist .layout')
if ($componentList.length == 0) {
alert('Components can be added only to pages and layouts.')
return;
}
var $component = $(this).clone(),
$iconInput = $component.find('[data-component-icon]'),
$componentContainer = $('.layout-relative', $component),
$configInput = $component.find('[data-inspector-config]'),
$aliasInput = $component.find('[data-component-default-alias]'),
$valuesInput = $component.find('[data-inspector-values]'),
$nameInput = $component.find('[data-component-name]'),
$classInput = $component.find('[data-inspector-class]'),
alias = $aliasInput.val(),
originalAlias = alias,
counter = 2,
existingAliases = []
$('div.layout-cell input[name="component_aliases[]"]', $componentList).each(function(){
existingAliases.push($(this).val())
})
while($.inArray(alias, existingAliases) !== -1) {
alias = originalAlias + counter
counter++
}
// Set the last alias used so dragComponents can use it
$('input[name="component_aliases[]"]', $(this)).val(alias)
$component.attr('data-component-attached', true)
$componentContainer.addClass($iconInput.val())
$iconInput.remove()
$componentContainer.attr('data-inspectable', '')
$componentContainer.attr('data-inspector-title', $component.find('span.name').text())
$componentContainer.attr('data-inspector-description', $component.find('span.description').text())
$componentContainer.attr('data-inspector-config', $configInput.val())
$componentContainer.attr('data-inspector-class', $classInput.val())
$configInput.remove()
$('input[name="component_names[]"]', $component).val($nameInput.val())
$nameInput.remove()
$('input[name="component_aliases[]"]', $component).val(alias)
$component.find('span.alias').text(alias)
$component.find('span.alias').text(alias)
$valuesInput.val($valuesInput.val().replace('--alias--', alias))
$aliasInput.remove()
$component.addClass('adding')
$componentList.append($component)
$componentList.closest('[data-control="toolbar"]').data('oc.dragScroll').goToElement($component)
$component.removeClass('adding')
$component.trigger('change')
updateComponentListClass($component.closest('.tab-pane'))
$(window).trigger('oc.updateUi')
})
})
function updateLayouts(form) {
$(form).request('onGetTemplateList', {
success: function(data) {
$('#cms-master-tabs > .tab-content select[name="settings[layout]"]').each(function(){
var
$select = $(this),
value = $select.val()
$select.find('option').remove()
$.each(data.layouts, function(layoutFile, layoutName){
$select.append($('<option>').attr('value', layoutFile).text(layoutName))
})
$select.trigger('pause.oc.changeMonitor')
$select.val(value)
$select.trigger('change')
$select.trigger('resume.oc.changeMonitor')
})
}
})
}
var CmsPage = function() {
this.updateTemplateList = function(type) {
var
$form = $('#cms-side-panel form[data-template-type='+type+']'),
templateList = type + 'List'
$form.request(templateList + '::onUpdate', {
complete: function() {
$('button[data-control=delete-template]', $form).trigger('oc.triggerOn.update')
}
})
}
}
$.oc.cmsPage = new CmsPage;
}(window.jQuery);