mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
ENHANCEMENT Integrating right panels ('insert image', etc.) in CMS with new layout manager, adjusting title bar to jQuery UI styling, making panel content scrollable
MINOR Updated cmsmain/leftandmain javascript to concrete API changes git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92609 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
d5ec175cfb
commit
9f4d0da80a
@ -188,6 +188,7 @@ class LeftAndMain extends Controller {
|
||||
Requirements::javascript(THIRDPARTY_DIR . '/jquery/ui/effects.scale.js');
|
||||
Requirements::javascript(THIRDPARTY_DIR . '/jquery/plugins/layout/jquery.layout.js');
|
||||
Requirements::javascript(THIRDPARTY_DIR . '/jquery/plugins/fitheighttoparent/jquery.fitheighttoparent.js');
|
||||
Requirements::javascript(CMS_DIR . '/javascript/ssui.core.js');
|
||||
// @todo Load separately so the CSS files can be inlined
|
||||
Requirements::css(THIRDPARTY_DIR . '/jquery/themes/smoothness/ui.all.css');
|
||||
|
||||
|
@ -480,3 +480,12 @@
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Insert Image" forms etc.
|
||||
*/
|
||||
#Form_EditorToolbarImageForm .field,
|
||||
#Form_EditorToolbarFlashForm .field,
|
||||
#Form_EditorToolbarLinkForm .field {
|
||||
margin-left: 0;
|
||||
}
|
@ -35,7 +35,8 @@ body {
|
||||
}
|
||||
|
||||
/* Overflow is handled by tabsets inside the panel */
|
||||
.ui-layout-center {
|
||||
.ui-layout-center,
|
||||
.ui-layout-east {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
@ -487,16 +488,11 @@ iframe {
|
||||
* This is our new right hand pane for inserting images and links etc
|
||||
*/
|
||||
#contentPanel {
|
||||
background-color: #fff;
|
||||
width: 205px;
|
||||
position: absolute;
|
||||
border: 1px solid #ACBBCC;
|
||||
top: 45px;
|
||||
padding: 0;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
}
|
||||
#contentPanel .content {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#contentPanel div,
|
||||
#contentPanel p#TargetBlank {
|
||||
@ -523,13 +519,9 @@ iframe {
|
||||
overflow-y: auto;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
#contentPanel fieldset {
|
||||
padding: 5px;
|
||||
}
|
||||
#contentPanel h2 {
|
||||
margin: -5px -5px 0 -5px;
|
||||
}
|
||||
#contentPanel .ui-dialog {
|
||||
width: auto;
|
||||
}
|
||||
#contentPanel .thumbnailstrip h2 {
|
||||
font-size: 1.1em;
|
||||
margin: 0;
|
||||
@ -549,7 +541,6 @@ iframe {
|
||||
background:#E9E9E9 none repeat scroll 0%;
|
||||
display:block;
|
||||
padding:3px;
|
||||
width:98%;
|
||||
}
|
||||
#contentPanel input.text {
|
||||
border:1px solid #A7A7A7;
|
||||
@ -560,6 +551,10 @@ iframe {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#contentPanel form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Image height and width inputs. We need to position them in the right places */
|
||||
#contentPanel input#Form_EditorToolbarImageForm_Width,
|
||||
#contentPanel input#Form_EditorToolbarFlashForm_Width {
|
||||
@ -613,7 +608,7 @@ iframe {
|
||||
border: 2px solid #e4e3e3;
|
||||
}
|
||||
#contentPanel div.Actions {
|
||||
margin: 2px 5px 0 0;
|
||||
margin: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
#contentPanel #FolderImages a.selectedImage img,
|
||||
|
@ -1,28 +1,35 @@
|
||||
(function($) {
|
||||
$('body.CMSMain').concrete('ss.leftAndMain', {
|
||||
$('body.CMSMain').concrete('ss', function($){return{
|
||||
|
||||
/**
|
||||
* Reference to jQuery.layout element
|
||||
*/
|
||||
MainLayout: null,
|
||||
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
|
||||
this.concrete("ss.leftAndMain").setMainLayout(this.concrete("ss.leftAndMain")._setupLayout());
|
||||
this.setMainLayout(this._setupLayout());
|
||||
|
||||
// artificially delay the resize event 200ms
|
||||
// to avoid overlapping height changes in different onresize() methods
|
||||
$(window).resize(function () {
|
||||
var timerID = "timerCMSMainResize";
|
||||
if (window[timerID]) clearTimeout(window[timerID]);
|
||||
window[timerID] = setTimeout(function() {self.concrete("ss.leftAndMain")._resizeChildren();}, 200);
|
||||
window[timerID] = setTimeout(function() {self._resizeChildren();}, 200);
|
||||
});
|
||||
|
||||
this.concrete("ss.leftAndMain")._resizeChildren();
|
||||
this._resizeChildren();
|
||||
|
||||
this._super();
|
||||
},
|
||||
|
||||
_resizeChildren: function() {
|
||||
$("#treepanes").accordion("resize");
|
||||
$('#sitetree_and_tools').fitHeightToParent();
|
||||
$("#treepanes", this).accordion("resize");
|
||||
$('#sitetree_and_tools', this).fitHeightToParent();
|
||||
$('#contentPanel form', this).fitHeightToParent();
|
||||
$('#contentPanel form fieldset', this).fitHeightToParent();
|
||||
$('#contentPanel form fieldset .content', this).fitHeightToParent();
|
||||
|
||||
this._super();
|
||||
},
|
||||
@ -45,7 +52,9 @@
|
||||
togglerTip_open: '',
|
||||
togglerTip_closed: '',
|
||||
resizerTip: '',
|
||||
sliderTip: ''
|
||||
sliderTip: '',
|
||||
onresize: function() {self._resizeChildren();},
|
||||
onopen: function() {self._resizeChildren();},
|
||||
},
|
||||
north: {
|
||||
slidable: false,
|
||||
@ -61,13 +70,12 @@
|
||||
},
|
||||
west: {
|
||||
size: 250,
|
||||
onresize: function() {self.concrete()._resizeChildren();},
|
||||
onopen: function() {self.concrete()._resizeChildren();},
|
||||
fxName: "none"
|
||||
},
|
||||
east: {
|
||||
initClosed: true,
|
||||
fxName: "none"
|
||||
fxName: "none",
|
||||
size: 250
|
||||
},
|
||||
center: {}
|
||||
});
|
||||
@ -81,12 +89,12 @@
|
||||
|
||||
return layout;
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* CMS-specific form behaviour
|
||||
*/
|
||||
$('#Form_EditForm').concrete({
|
||||
$('#Form_EditForm').concrete('ss', function($){return{
|
||||
onmatch: function() {
|
||||
// Alert the user on change of page-type - this might have implications
|
||||
// on the available form fields etc.
|
||||
@ -98,13 +106,13 @@
|
||||
|
||||
this.find(':input[name=ParentID]')
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* ParentType / ParentID field combination - mostly toggling between
|
||||
* the two radiobuttons and setting the hidden "ParentID" field
|
||||
*/
|
||||
$('#Form_EditForm_ParentType').concrete({
|
||||
$('#Form_EditForm_ParentType').concrete('ss', function($){return{
|
||||
onmatch : function() {
|
||||
var parentTypeRootEl = $('#Form_EditForm_ParentType_root');
|
||||
var parentTypeSubpageEl = $('#Form_EditForm_ParentType_subpage');
|
||||
@ -130,13 +138,13 @@
|
||||
$('#ParentID').show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* Email containing the link to the archived version of the page.
|
||||
* Visible on readonly older versions of a specific page at the moment.
|
||||
*/
|
||||
$('#Form_EditForm .Actions #Form_EditForm_action_email').concrete({
|
||||
$('#Form_EditForm .Actions #Form_EditForm_action_email').concrete('ss', function($){return{
|
||||
onclick: function(e) {
|
||||
window.open(
|
||||
'mailto:?subject='
|
||||
@ -148,13 +156,13 @@
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* Open a printable representation of the form in a new window.
|
||||
* Used for readonly older versions of a specific page.
|
||||
*/
|
||||
$('#Form_EditForm .Actions #Form_EditForm_action_print').concrete({
|
||||
$('#Form_EditForm .Actions #Form_EditForm_action_print').concrete('ss', function($){return{
|
||||
onclick: function(e) {
|
||||
var printURL = $(this[0].form).attr('action').replace(/\?.*$/,'')
|
||||
+ '/printable/'
|
||||
@ -165,21 +173,34 @@
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* A "rollback" to a specific version needs user confirmation.
|
||||
*/
|
||||
$('#Form_EditForm .Actions #Form_EditForm_action_rollback').concrete({
|
||||
$('#Form_EditForm .Actions #Form_EditForm_action_rollback').concrete('ss', function($){return{
|
||||
onclick: function(e) {
|
||||
// @todo i18n
|
||||
return confirm("Do you really want to copy the published content to the stage site?");
|
||||
}
|
||||
}});
|
||||
|
||||
/**
|
||||
* All forms in the right content panel should have closeable jQuery UI style titles.
|
||||
*/
|
||||
$('#contentPanel form').concrete('ss', function($){return{
|
||||
onmatch: function() {
|
||||
// Style as title bar
|
||||
this.find(':header:first').titlebar({
|
||||
closeButton:true
|
||||
});
|
||||
// The close button should close the east panel of the layout
|
||||
this.find(':header:first .ui-dialog-titlebar-close').bind('click', function(e) {
|
||||
$('body.CMSMain').concrete('ss').MainLayout().close('east');
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}});
|
||||
|
||||
})(jQuery);
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
// @todo remove
|
||||
jQuery.concrete.triggerMatching();
|
||||
});
|
@ -10,12 +10,17 @@
|
||||
* - beforeValidate
|
||||
* - afterValidate
|
||||
*/
|
||||
$('.LeftAndMain').concrete('ss.leftAndMain', {
|
||||
$('.LeftAndMain').concrete('ss', function($){return{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PingIntervalSeconds: 5*60,
|
||||
|
||||
onmatch: function() {
|
||||
this.concrete("ss.leftAndMain")._setupPinging();
|
||||
this.concrete("ss.leftAndMain")._setupButtons();
|
||||
this._setupPinging();
|
||||
this._setupButtons();
|
||||
this._resizeChildren();
|
||||
|
||||
this._super();
|
||||
},
|
||||
@ -23,7 +28,7 @@
|
||||
_setupPinging: function() {
|
||||
// setup pinging for login expiry
|
||||
setInterval(function() {
|
||||
$.get("Security/ping");
|
||||
jQuery.get("Security/ping");
|
||||
}, this.PingIntervalSeconds() * 1000);
|
||||
},
|
||||
|
||||
@ -52,15 +57,30 @@
|
||||
$(this).removeClass('ui-state-focus');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Resize elements in center panel
|
||||
* to fit the boundary box provided by the layout manager
|
||||
*/
|
||||
_resizeChildren: function() {
|
||||
$('#Form_EditForm').fitHeightToParent();
|
||||
$('#Form_EditForm fieldset', this).fitHeightToParent();
|
||||
// Order of resizing is important: Outer to inner
|
||||
// TODO Only supports two levels of tabs at the moment
|
||||
$('#Form_EditForm fieldset > .ss-tabset', this).fitHeightToParent();
|
||||
$('#Form_EditForm fieldset > .ss-tabset > .tab', this).fitHeightToParent();
|
||||
$('#Form_EditForm fieldset > .ss-tabset > .tab > .ss-tabset', this).fitHeightToParent();
|
||||
$('#Form_EditForm fieldset > .ss-tabset > .tab > .ss-tabset > .tab', this).fitHeightToParent();
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* Base edit form, provides ajaxified saving
|
||||
* and reloading itself through the ajax return values.
|
||||
* Takes care of resizing tabsets within the layout container.
|
||||
*/
|
||||
$('#Form_EditForm').concrete('ss.editForm',{
|
||||
$('#Form_EditForm').concrete('ss',function($){return{
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
|
||||
@ -69,14 +89,12 @@
|
||||
$(window).resize(function () {
|
||||
var timerID = "timerLeftAndMainResize";
|
||||
if (window[timerID]) clearTimeout(window[timerID]);
|
||||
window[timerID] = setTimeout(function() {self.concrete('ss.editForm')._resizeChildren();}, 200);
|
||||
window[timerID] = setTimeout(function() {self._resizeChildren();}, 200);
|
||||
});
|
||||
|
||||
this.concrete('ss.editForm')._resizeChildren();
|
||||
|
||||
// trigger resize whenever new tabs are shown
|
||||
// @todo This is called multiple times when tabs are loaded
|
||||
this.find('.ss-tabset').bind('tabsshow', function() {self.concrete('ss.editForm')._resizeChildren();});
|
||||
this.find('.ss-tabset').bind('tabsshow', function() {self._resizeChildren();});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -181,37 +199,22 @@
|
||||
if($('input#Form_EditForm_Title') && $('input#Form_EditForm_Title').value.match(/^new/i)) {
|
||||
$('input#Form_EditForm_Title').select();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resize elements in center panel
|
||||
* to fit the boundary box provided by the layout manager
|
||||
*/
|
||||
_resizeChildren: function() {
|
||||
this.fitHeightToParent();
|
||||
$('fieldset', this).fitHeightToParent();
|
||||
// Order of resizing is important: Outer to inner
|
||||
// TODO Only supports two levels of tabs at the moment
|
||||
$('fieldset > .ss-tabset', this).fitHeightToParent();
|
||||
$('fieldset > .ss-tabset > .tab', this).fitHeightToParent();
|
||||
$('fieldset > .ss-tabset > .tab > .ss-tabset', this).fitHeightToParent();
|
||||
$('fieldset > .ss-tabset > .tab > .ss-tabset > .tab', this).fitHeightToParent();
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* All buttons in the right CMS form go through here by default.
|
||||
* We need this onclick overloading because we can't get to the
|
||||
* clicked button from a form.onsubmit event.
|
||||
*/
|
||||
$('#Form_EditForm .Actions :submit').concrete({
|
||||
$('#Form_EditForm .Actions :submit').concrete('ss', function($){return{
|
||||
onclick: function(e) {
|
||||
$(this[0].form).ajaxSubmit(this);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
$('#TreeActions').concrete({
|
||||
$('#TreeActions').concrete('ss', function($){return{
|
||||
onmatch: function() {
|
||||
// setup "create", "search", "batch actions" layers above tree
|
||||
this.tabs({
|
||||
@ -219,27 +222,22 @@
|
||||
collapsible: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
/**
|
||||
* Link for editing the profile for a logged-in member
|
||||
* through a popup. Required "greybox" javascript library.
|
||||
*/
|
||||
$('#EditMemberProfile').concrete({
|
||||
$('#EditMemberProfile').concrete('ss', function($){return{
|
||||
onclick: function(e) {
|
||||
GB_show('Edit Profile', this.attr('href'), 290, 500);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
|
||||
})(jQuery);
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
// @todo remove
|
||||
jQuery.concrete.triggerMatching();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
@ -263,9 +261,7 @@ Behaviour.register({
|
||||
window.location.href = this.getElementsByTagName('a')[0].href;
|
||||
Event.stop(event);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
93
javascript/ssui.core.js
Normal file
93
javascript/ssui.core.js
Normal file
@ -0,0 +1,93 @@
|
||||
(function($) {
|
||||
$.widget("ssui.titlebar", {
|
||||
_init: function() {
|
||||
this.originalTitle = this.element.attr('title');
|
||||
|
||||
var self = this;
|
||||
var options = this.options;
|
||||
|
||||
var title = options.title || this.originalTitle || ' ';
|
||||
var titleId = $.ui.dialog.getTitleId(this.element);
|
||||
|
||||
this.element.parent().addClass('ui-dialog');
|
||||
|
||||
var uiDialogTitlebar = this.element.
|
||||
addClass(
|
||||
'ui-dialog-titlebar ' +
|
||||
'ui-widget-header ' +
|
||||
'ui-corner-all ' +
|
||||
'ui-helper-clearfix'
|
||||
);
|
||||
|
||||
// By default, the
|
||||
|
||||
if(options.closeButton) {
|
||||
var uiDialogTitlebarClose = $('<a href="#"/>')
|
||||
.addClass(
|
||||
'ui-dialog-titlebar-close ' +
|
||||
'ui-corner-all'
|
||||
)
|
||||
.attr('role', 'button')
|
||||
.hover(
|
||||
function() {
|
||||
uiDialogTitlebarClose.addClass('ui-state-hover');
|
||||
},
|
||||
function() {
|
||||
uiDialogTitlebarClose.removeClass('ui-state-hover');
|
||||
}
|
||||
)
|
||||
.focus(function() {
|
||||
uiDialogTitlebarClose.addClass('ui-state-focus');
|
||||
})
|
||||
.blur(function() {
|
||||
uiDialogTitlebarClose.removeClass('ui-state-focus');
|
||||
})
|
||||
.mousedown(function(ev) {
|
||||
ev.stopPropagation();
|
||||
})
|
||||
.appendTo(uiDialogTitlebar);
|
||||
|
||||
var uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
|
||||
.addClass(
|
||||
'ui-icon ' +
|
||||
'ui-icon-closethick'
|
||||
)
|
||||
.text(options.closeText)
|
||||
.appendTo(uiDialogTitlebarClose);
|
||||
}
|
||||
|
||||
var uiDialogTitle = $('<span/>')
|
||||
.addClass('ui-dialog-title')
|
||||
.attr('id', titleId)
|
||||
.html(title)
|
||||
.prependTo(uiDialogTitlebar);
|
||||
|
||||
uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.element
|
||||
.unbind('.dialog')
|
||||
.removeData('dialog')
|
||||
.removeClass('ui-dialog-content ui-widget-content')
|
||||
.hide().appendTo('body');
|
||||
|
||||
(this.originalTitle && this.element.attr('title', this.originalTitle));
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.ssui.titlebar, {
|
||||
version: "0.0.1",
|
||||
defaults: {
|
||||
title: '',
|
||||
closeButton: false,
|
||||
closeText: 'close'
|
||||
},
|
||||
|
||||
uuid: 0,
|
||||
|
||||
getTitleId: function($el) {
|
||||
return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
|
||||
}
|
||||
});
|
||||
}(jQuery));
|
@ -23,7 +23,7 @@
|
||||
$Right
|
||||
</div>
|
||||
|
||||
<div class="ui-layout-east">
|
||||
<div class="ui-layout-east" id="contentPanel">
|
||||
<% control EditorToolbar %>
|
||||
$ImageForm
|
||||
$LinkForm
|
||||
|
Loading…
Reference in New Issue
Block a user