diff --git a/_config.php b/_config.php
index 5d06b200..1d2d5bc9 100644
--- a/_config.php
+++ b/_config.php
@@ -17,4 +17,37 @@ Director::addRules(50, array(
));
CMSMenu::populate_menu();
+
+HtmlEditorConfig::get('cms')->setOptions(array(
+ 'mode' => 'none',
+ 'language' => i18n::get_tinymce_lang(),
+ 'content_css' => 'cms/css/editor.css, '.(SSViewer::current_theme() ? THEMES_DIR . "/" . SSViewer::current_theme() : project()) . "/css/editor.css",
+
+ 'body_class' => 'typography',
+ 'document_base_url' => Director::absoluteBaseURL(),
+
+ 'urlconverter_callback' => "nullConverter",
+ 'setupcontent_callback' => "sapphiremce_setupcontent",
+ 'cleanup_callback' => "sapphiremce_cleanup",
+
+ 'template_templates' => array(
+ array( 'title' => "Three column", 'src' => "assets/snippet.html", 'description' => "A simple 3 column layout" )
+ ),
+
+ 'use_native_selects' => true, // fancy selects are bug as of SS 2.3.0
+ 'valid_elements' => "+a[id|rel|rev|dir|tabindex|accesskey|type|name|href|target|title|class],-strong/-b[class],-em/-i[class],-strike[class],-u[class],#p[id|dir|class|align],-ol[class],-ul[class],-li[class],br,img[id|dir|longdesc|usemap|class|src|border|alt=|title|width|height|align],-sub[class],-sup[class],-blockquote[dir|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|dir|id|style],-tr[id|dir|class|rowspan|width|height|align|valign|bgcolor|background|bordercolor|style],tbody[id|class|style],thead[id|class|style],tfoot[id|class|style],-td[id|dir|class|colspan|rowspan|width|height|align|valign|scope|style],-th[id|dir|class|colspan|rowspan|width|height|align|valign|scope|style],caption[id|dir|class],-div[id|dir|class|align|style],-span[class|align],-pre[class|align],address[class|align],-h1[id|dir|class|align],-h2[id|dir|class|align],-h3[id|dir|class|align],-h4[id|dir|class|align],-h5[id|dir|class|align],-h6[id|dir|class|align],hr[class],dd[id|class|title|dir],dl[id|class|title|dir],dt[id|class|title|dir]",
+ 'extended_valid_elements' => "img[class|src|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name|usemap],iframe[src|name|width|height|align|frameborder|marginwidth|marginheight|scrolling],object[width|height|data|type],param[name|value],map[class|name|id],area[shape|coords|href|target|alt]"
+));
+
+
+HtmlEditorConfig::get('cms')->disablePlugins('blockquote');
+HtmlEditorConfig::get('cms')->enablePlugins('media', '../../tinymce_ssbuttons', 'fullscreen');
+
+HtmlEditorConfig::get('cms')->insertButtonsBefore('formatselect', 'styleselect');
+HtmlEditorConfig::get('cms')->insertButtonsBefore('advcode', 'ssimage', 'ssflash', 'sslink', 'unlink', 'anchor', 'separator' );
+HtmlEditorConfig::get('cms')->insertButtonsAfter ('advcode', 'fullscreen', 'separator');
+
+HtmlEditorConfig::get('cms')->removeButtons('tablecontrols');
+HtmlEditorConfig::get('cms')->addButtonsToLine(3, 'tablecontrols');
+
?>
diff --git a/code/CMSMain.php b/code/CMSMain.php
index bd00be28..ff36da37 100644
--- a/code/CMSMain.php
+++ b/code/CMSMain.php
@@ -40,7 +40,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'dialog',
'duplicate',
'duplicatewithchildren',
- 'filtersitetree',
'getpagecount',
'getversion',
'publishall',
@@ -56,7 +55,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'EditForm',
'AddPageOptionsForm',
'SiteTreeAsUL',
- 'getshowdeletedsubtree'
+ 'getshowdeletedsubtree',
+ 'getfilteredsubtree',
+ 'batchactions'
);
/**
@@ -75,13 +76,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return array(
'Title' => _t('CMSMain.TITLEOPT', 'Title', 0, 'The dropdown title in CMSMain left SiteTreeFilterOptions'),
'MenuTitle' => _t('CMSMain.MENUTITLEOPT', 'Navigation Label', 0, 'The dropdown title in CMSMain left SiteTreeFilterOptions'),
- 'ClassName' => _t('CMSMain.PAGETYPEOPT', 'Page Type', 0, "The dropdown title in CMSMain left SiteTreeFilterOptions"),
'Status' => _t('CMSMain.STATUSOPT', 'Status', 0, "The dropdown title in CMSMain left SiteTreeFilterOptions"),
'MetaDescription' => _t('CMSMain.METADESCOPT', 'Description', 0, "The dropdown title in CMSMain left SiteTreeFilterOptions"),
'MetaKeywords' => _t('CMSMain.METAKEYWORDSOPT', 'Keywords', 0, "The dropdown title in CMSMain left SiteTreeFilterOptions")
);
}
-
+
public function init() {
parent::init();
@@ -110,18 +110,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$spellcheckSpec = array();
foreach($spellcheckLangs as $lang => $title) $spellcheckSpec[] = "{$title}={$lang}";
+ HtmlEditorConfig::get('cms')->setOption('spellchecker_languages', '+' . implode(',', $spellcheckSpec));
+
+ // @todo Do we need this - I'm pretty sure not, since HtmlEditorField#Field() will include it on being called.
+ // The only time you might need it is if you are creating an textarea.htmlfield yourself, in which case bad things are going to happen now we've moved configuration
// We don't want this showing up in every ajax-response, it should always be present in a CMS-environment
if(!Director::is_ajax()) {
Requirements::javascript(MCE_ROOT . "tiny_mce_src.js");
- Requirements::javascriptTemplate(CMS_DIR . "/javascript/tinymce.template.js", array(
- "ContentCSS" => (SSViewer::current_theme() ? THEMES_DIR . "/" . SSViewer::current_theme() : project()) . "/css/editor.css",
- "BaseURL" => Director::absoluteBaseURL(),
- "Lang" => i18n::get_tinymce_lang(),
- 'SpellcheckLangs' => '+' . implode(',', $spellcheckSpec)
- ));
}
- // Always block the HtmlEditorField.js otherwise it will be sent with an ajax request
- Requirements::block(SAPPHIRE_DIR . '/javascript/HtmlEditorField.js');
Requirements::javascript(CMS_DIR . '/javascript/CMSMain.js');
Requirements::javascript(CMS_DIR . '/javascript/CMSMain_left.js');
@@ -186,7 +182,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return $tree;
}
+
+ public function getfilteredsubtree() {
+ // Get the tree
+ $tree = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID'], null, 'cmsMainMarkingFilterFunction');
+ // Trim off the outer tag
+ $tree = ereg_replace('^[ \t\r\n]*
]*>','', $tree);
+ $tree = ereg_replace('
]*>[ \t\r\n]*$','', $tree);
+
+ return $tree;
+ }
+
/**
* Returns the SiteTree columns that can be filtered using the the Site Tree Search button as a DataObjectSet
*/
@@ -205,44 +212,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$dateField = new CalendarDateField('SiteTreeFilterDate');
return $dateField->Field();
}
-
- /**
- * Returns a filtered Site Tree
- */
- public function filtersitetree() {
- // Pre-cache sitetree version numbers for querying efficiency
- Versioned::prepopulate_versionnumber_cache("SiteTree", "Stage");
- Versioned::prepopulate_versionnumber_cache("SiteTree", "Live");
-
- $className = 'SiteTree';
- $rootID = null;
- $obj = $rootID ? $this->getRecord($rootID) : singleton($className);
- $obj->setMarkingFilterFunction('cmsMainMarkingFilterFunction');
- $obj->markPartialTree();
-
- if($p = $this->currentPage()) $obj->markToExpose($p);
-
- // getChildrenAsUL is a flexible and complex way of traversing the tree
- $siteTree = $obj->getChildrenAsUL("", '
- "
";
- }
-
- return $siteTree;
-
- }
+ public function SiteTreeFilterPageTypeField() {
+ $types = SiteTree::page_type_classes(); array_unshift($types, 'All');
+ $optionsetField = new DropdownField('ClassName', 'ClassName', array_combine($types, $types), 'Any');
+ return $optionsetField->Field();
+ }
public function generateDataTreeHints() {
$classes = ClassInfo::subclassesFor( $this->stat('tree_class') );
@@ -975,54 +949,12 @@ JS;
'DialogType' => 'alert'
))->renderWith('Dialog');
}
-
+
/**
- * Publishes a number of items.
- * Called by AJAX
+ * Batch Actions Handler
*/
- public function publishitems() {
- // This method can't be called without ajax.
- if(!Director::is_ajax()) {
- Director::redirectBack();
- return;
- }
-
- $ids = split(' *, *', $this->requestParams['csvIDs']);
-
- $notifications = array();
-
- $idList = array();
-
- // make sure all the ids are numeric.
- // Add all the children to the list of IDs if they are missing
- foreach($ids as $id) {
- $brokenPageList = '';
- if(is_numeric($id)) {
- $record = DataObject::get_by_id($this->stat('tree_class'), $id);
-
- if($record) {
- if($record && !$record->canPublish()) return Security::permissionFailure($this);
-
- // Publish this page
- $record->doPublish();
-
- // Now make sure the 'changed' icon is removed
- $publishedRecord = DataObject::get_by_id($this->stat('tree_class'), $id);
- $JS_title = Convert::raw2js($publishedRecord->TreeTitle());
- FormResponse::add("\$('sitetree').setNodeTitle($id, '$JS_title');");
- FormResponse::add("$('Form_EditForm').reloadIfSetTo($record->ID);");
- $record->destroy();
- unset($record);
- }
- }
- }
-
- if (sizeof($ids) > 1) $message = sprintf(_t('CMSMain.PAGESPUB', "%d pages published "), sizeof($ids));
- else $message = sprintf(_t('CMSMain.PAGEPUB', "%d page published "), sizeof($ids));
-
- FormResponse::add('statusMessage("'.$message.'","good");');
-
- return FormResponse::respond();
+ function batchactions() {
+ return new CMSBatchActionHandler($this, 'batchactions');
}
/**
@@ -1045,97 +977,10 @@ JS;
}
/**
- * Delete a number of items.
- * This code supports notification
+ * Returns a list of batch actions
*/
- public function deleteitems() {
- // This method can't be called without ajax.
- if(!Director::is_ajax()) {
- Director::redirectBack();
- return;
- }
-
- $ids = split(' *, *', $_REQUEST['csvIDs']);
-
- $notifications = array();
-
- $idList = array();
-
- // make sure all the ids are numeric.
- // Add all the children to the list of IDs if they are missing
- foreach($ids as $id) {
- $brokenPageList = '';
- if(is_numeric($id)) {
- $record = DataObject::get_by_id($this->stat('tree_class'), $id);
-
- if($record) {
- if($record && !$record->canDelete()) return Security::permissionFailure($this);
-
- // add all the children for this record if they are not already in the list
- // this check is a little slower but will prevent circular dependencies
- // (should they exist, which they probably shouldn't) from causing
- // the function to not terminate
- $children = $record->AllChildren();
-
- if( $children )
- foreach( $children as $child )
- if( array_search( $child->ID, $ids ) !== FALSE )
- $ids[] = $child->ID;
-
- if($record->hasMethod('BackLinkTracking')) {
- $brokenPages = $record->BackLinkTracking();
- foreach($brokenPages as $brokenPage) {
- $brokenPageList .= "
" . $brokenPage->Breadcrumbs(3, true) . "
";
- $brokenPage->HasBrokenLink = true;
- $notifications[$brokenPage->OwnerID][] = $brokenPage;
- $brokenPage->writeWithoutVersion();
- }
- }
-
- $oldID = $record->ID;
- $record->delete();
- $record->destroy();
-
- // DataObject::delete_by_id($this->stat('tree_class'), $id);
-
- // check to see if the record exists on the live site, if it doesn't remove the tree node
- $liveRecord = Versioned::get_one_by_stage( $this->stat('tree_class'), 'Live', "\"{$this->stat('tree_class')}\".\"ID\"={$id}");
-
- if($liveRecord) {
- $liveRecord->IsDeletedFromStage = true;
- $title = Convert::raw2js($liveRecord->TreeTitle());
- FormResponse::add("$('sitetree').setNodeTitle($oldID, '$title');");
- FormResponse::add("$('Form_EditForm').reloadIfSetTo($oldID);");
- } else {
- FormResponse::add("var node = $('sitetree').getTreeNodeByIdx('$id');");
- FormResponse::add("if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node);");
- FormResponse::add("$('Form_EditForm').reloadIfSetTo($oldID);");
- }
- }
- }
- }
-
- if($notifications) foreach($notifications as $memberID => $pages) {
- if(class_exists('Page_BrokenLinkEmail')) {
- $email = new Page_BrokenLinkEmail();
- $email->populateTemplate(new ArrayData(array(
- "Recipient" => DataObject::get_by_id("Member", $memberID),
- "BrokenPages" => new DataObjectSet($pages),
- )));
- $email->debug();
- $email->send();
- }
- }
-
- if (sizeof($ids) > 1) $message = sprintf(_t('CMSMain.PAGESDEL', "%d pages deleted "), sizeof($ids));
- else $message = sprintf(_t('CMSMain.PAGEDEL', "%d page deleted "), sizeof($ids));
- if(isset($brokenPageList) && $brokenPageList != '') {
- $message .= _t('CMSMain.NOWBROKEN'," The following pages now have broken links:")."
" . addslashes($brokenPageList) . "
" . _t('CMSMain.NOWBROKEN2',"Their owners have been emailed and they will fix up those pages.");
- }
-
- FormResponse::add('statusMessage("'.$message.'","good");');
-
- return FormResponse::respond();
+ function BatchActionList() {
+ return $this->batchactions()->batchActionList();
}
/**
@@ -1435,6 +1280,7 @@ $filterCache = array();
// TODO: Find way to put this in a class
function cmsMainMarkingFilterFunction($node) {
+ global $filterCache;
// Expand all nodes
// $node->markingFinished();
@@ -1458,6 +1304,11 @@ function cmsMainMarkingFilterFunction($node) {
$failed_filter = true;
}
}
+ // Check the ClassName
+ if (!empty($_REQUEST['ClassName']) && $_REQUEST['ClassName'] != 'Any') {
+ if ($node->ClassName != $_REQUEST['ClassName']) $failed_filter = true;
+ }
+
// Now check if a specified Criteria attribute matches
foreach (CMSMain::T_SiteTreeFilterOptions() as $key => $value)
{
diff --git a/code/LeftAndMain.php b/code/LeftAndMain.php
index 07c8ca8e..c2acea8b 100644
--- a/code/LeftAndMain.php
+++ b/code/LeftAndMain.php
@@ -153,6 +153,9 @@ class LeftAndMain extends Controller {
// Audit logging hook
if(empty($_REQUEST['executeForm']) && !Director::is_ajax()) $this->extend('accessedCMS');
+
+ // Override HtmlEditorField's config with our own
+ HtmlEditorconfig::set_active('cms');
Requirements::css(CMS_DIR . '/css/typography.css');
Requirements::css(CMS_DIR . '/css/layout.css');
@@ -465,10 +468,18 @@ class LeftAndMain extends Controller {
* @param $childrenMethod The method to call to get the children of the tree. For example,
* Children, AllChildrenIncludingDeleted, or AllHistoricalChildren
*/
- function getSiteTreeFor($className, $rootID = null,
- $childrenMethod = "AllChildrenIncludingDeleted") {
+ function getSiteTreeFor($className, $rootID = null, $childrenMethod = null, $filterFunction = null) {
+ // Default childrenMethod
+ if (!$childrenMethod) $childrenMethod = 'AllChildrenIncludingDeleted';
+
+ // Get the tree root
$obj = $rootID ? $this->getRecord($rootID) : singleton($className);
+
+ // Mark the nodes of the tree to return
+ if ($filterFunction) $obj->setMarkingFilterFunction($filterFunction);
$obj->markPartialTree(30, $this, $childrenMethod);
+
+ // Ensure current page is exposed
if($p = $this->currentPage()) $obj->markToExpose($p);
// getChildrenAsUL is a flexible and complex way of traversing the tree
diff --git a/css/cms_left.css b/css/cms_left.css
index 6d90ea38..73155920 100644
--- a/css/cms_left.css
+++ b/css/cms_left.css
@@ -374,14 +374,15 @@ ul.tree span.untranslated a:visited {
}
#left form.actionparams div.SearchCriteria {
- width: 40%;
+ width: 28%;
overflow: hidden;
float: left;
}
-#left form.actionparams input.SearchCriteria {
- width: 43%;
+#left form.actionparams input.SearchCriteria, #left form.actionparams #InputSiteTreeFilterClassName select {
+ width: 60%;
float: left;
+ margin: 0;
}
#left form.actionparams #InputSiteTreeFilterDate .calendar {
margin-left: -96px;
diff --git a/css/layout.css b/css/layout.css
index 0b2bd9b4..f677ce23 100644
--- a/css/layout.css
+++ b/css/layout.css
@@ -357,17 +357,25 @@ body.stillLoading select {
padding-left: 5px;
position: relative;
}
- #SearchBox #SiteTreeSearchTerm {
- padding: 1px 0 2px 0;
+ #SearchControls {
+ float: left;
+ position: relative;
+ margin-top:2px;
+ }
+ #SearchControls label {
+ display: none;
+ }
+ #SearchControls select#SiteTreeFilterAddCriteria {
+ width: 8.8em;
+ padding:1px 0; margin:0;
}
-
#searchIndicator {
display: none;
width: 16px;
height: 16px;
background: #EFEFEF url(../images/network-save.gif) no-repeat;
position: absolute;
- left: 145px;
+ left: 95px;
top: 2px;
}
#searchIndicator.loading {
@@ -379,13 +387,6 @@ body.stillLoading select {
padding-left: 5px;
margin-bottom: 4px;
}
- #addCriteria {
- float: left;
- width: 100%;
- }
- #addCriteria label {
- display: none;
- }
#sitetree_ul, ul#sitetree {
padding: 3px 0 0 3px;
clear: left;
diff --git a/javascript/CMSMain_left.js b/javascript/CMSMain_left.js
index c47b2d4f..cc588e80 100755
--- a/javascript/CMSMain_left.js
+++ b/javascript/CMSMain_left.js
@@ -129,9 +129,9 @@ ShowDeletedPagesAction.prototype = {
onclick : function() {
if(this.checked) {
- SiteTreeHandlers.loadTree_url = SiteTreeHandlers.controller_url + '/getshowdeletedsubtree';
+ $('sitetree').setCustomURL(SiteTreeHandlers.controller_url+'/getshowdeletedsubtree');
} else {
- SiteTreeHandlers.loadTree_url = SiteTreeHandlers.controller_url + '/getsubtree';
+ $('sitetree').clearCustomURL();
}
// We can't update the tree while it's draggable; it gets b0rked.
@@ -144,13 +144,8 @@ ShowDeletedPagesAction.prototype = {
var indicator = $('checkboxActionIndicator');
indicator.style.display = 'block';
- var url = SiteTreeHandlers.loadTree_url + '?ID=0&ajax=1';
- if($('LangSelector')) url += "&locale=" + $('LangSelector').value;
-
- var request = new Ajax.Request(url, {
- onSuccess: function(response) {
- $('sitetree').innerHTML = response.responseText;
- SiteTree.applyTo($('sitetree'));
+ $('sitetree').reload({
+ onSuccess: function() {
if(__makeDraggableAfterUpdate) $('sitetree').makeDraggable();
indicator.style.display = 'none';
},
@@ -161,6 +156,107 @@ ShowDeletedPagesAction.prototype = {
}
}
+/**
+ * Show only drafts checkbox click action
+ */
+showonlydrafts = Class.create();
+showonlydrafts.applyTo('#publishpage_show_drafts');
+showonlydrafts.prototype = {
+ onclick : function() {
+ if(this.checked) {
+ $('sitetree').setCustomURL(SiteTreeHandlers.controller_url+'/getfilteredsubtree', {Status:'Saved'});
+ } else {
+ $('sitetree').clearCustomURL();
+ }
+
+ $('sitetree').reload({
+ onSuccess: function() {
+ statusMessage(ss.i18n._t('CMSMAIN.FILTEREDTREE'),'good');
+ },
+ onFailure: function(response) {
+ errorMessage(ss.i18n.sprintf(
+ ss.i18n._t('CMSMAIN.ERRORFILTERPAGES'),
+ response.responseText
+ ));
+ }
+ });
+ }
+}
+
+/**
+ * Control the site tree filter
+ */
+SiteTreeFilterForm = Class.create();
+SiteTreeFilterForm.applyTo('form#search_options');
+SiteTreeFilterForm.prototype = {
+ initialize: function() {
+ var self = this;
+ Form.getElements(this).each(function(el){
+ if (el.type == 'submit') el.onclick = function(){self.clicked = $F(this); console.log(self.clicked)};
+ });
+ },
+ onsubmit: function() {
+ var filters = $H();
+
+ if (this.clicked == 'Search') {
+ Form.getElements(this).each(function(el){
+ if (el.type == 'text') {
+ if ($F(el)) filters[el.name] = $F(el);
+ }
+ else if (el.type == 'select-one') {
+ if ($F(el) && $F(el) != 'All') filters[el.name] = $F(el);
+ }
+ });
+ }
+ else {
+ Form.getElements(this).each(function(el){
+ if (el.type == 'text') $(el).clear();
+ else if (el.type == 'select-one') el.value = 'All';
+ });
+ document.getElementsBySelector('.SearchCriteriaContainer', this).each(function(el){
+ Element.hide(el);
+ })
+ }
+
+ if (filters.keys().length) {
+ // Set new URL
+ $('sitetree').setCustomURL(SiteTreeHandlers.controller_url + '/getfilteredsubtree', filters);
+
+ // Disable checkbox tree controls that currently don't work with search.
+ // @todo: Make them work together
+ if ($('sitetree').isDraggable) $('sitetree').stopBeingDraggable();
+ document.getElementsBySelector('.checkboxAboveTree input[type=checkbox]').each(function(el){
+ el.value = false; el.disabled = true;
+ })
+ }
+ else {
+ // Reset URL to default
+ $('sitetree').clearCustomURL();
+
+ // Enable checkbox tree controls
+ document.getElementsBySelector('.checkboxAboveTree input[type=checkbox]').each(function(el){
+ el.disabled = false;
+ })
+ }
+
+ $('SiteTreeSearchButton').className = $('SiteTreeSearchClearButton').className = 'hidden';
+ $('searchIndicator').className = 'loading';
+
+ $('sitetree').reload({
+ onSuccess : function(response) {
+ $('SiteTreeSearchButton').className = $('SiteTreeSearchClearButton').className = 'action';
+ $('searchIndicator').className = '';
+ statusMessage('Filtered tree','good');
+ },
+ onFailure : function(response) {
+ errorMessage('Could not filter site tree ' + response.responseText);
+ }
+ });
+
+ return false;
+ }
+}
+
/**
* Add Criteria Drop-down onchange action which allows more criteria to be shown
*/
@@ -210,37 +306,6 @@ batchactionsclass.prototype = {
}
}
-/**
- * Show only drafts checkbox click action
- */
-showonlydrafts = Class.create();
-showonlydrafts.applyTo('#publishpage_show_drafts');
-showonlydrafts.prototype = {
- onclick : function() {
- if (0 == $('SiteTreeIsFiltered').value) {
- // Show all items in Site Tree again
- new Ajax.Request( 'admin/filterSiteTree?Status=Saved&ajax=1', {
- onSuccess: function( response ) {
- $('sitetree_ul').innerHTML = response.responseText;
- Behaviour.apply($('sitetree_ul'));
- $('SiteTreeIsFiltered').value = 1;
- $('batchactions').multiselectTransform();
- statusMessage(ss.i18n._t('CMSMAIN.FILTEREDTREE'),'good');
- },
- onFailure : function(response) {
- errorMessage(ss.i18n.sprintf(
- ss.i18n._t('CMSMAIN.ERRORFILTERPAGES'),
- response.responseText
- ));
- }
- });
- } else {
- batchActionGlobals.unfilterSiteTree();
- }
- }
-}
-
-
// batchActionGlobals is needed because calls to observeMethod doesn't seem to preserve instance variables so a Prototype can't be used
batchActionGlobals = {
selectedNodes: { },
@@ -337,25 +402,39 @@ batchActionGlobals = {
* Publish selected pages action
*/
publishpage = Class.create();
-publishpage.applyTo('#Form_PublishItemsForm');
+publishpage.applyTo('#batchactions_options');
publishpage.prototype = {
onsubmit : function() {
csvIDs = batchActionGlobals.getCsvIds();
if(csvIDs) {
+ var optionEl = $('choose_batch_action').options[$('choose_batch_action').selectedIndex];
+ var actionText = optionEl.text;
+ var optionParams = eval(optionEl.className);
+ var ingText = optionParams.doingText;
+
+ // Confirmation
+ if(!confirm("You have " + batchActionGlobals.count + " pages selected.\n\nDo your really want to " + actionText.toLowerCase() + "?")) {
+ return false;
+ }
+
this.elements.csvIDs.value = csvIDs;
+
+ // Select form submission URL
+ this.action = $('choose_batch_action').value;
- statusMessage(ss.i18n._t('CMSMAIN.PUBLISHINGPAGES'));
+ // Loading indicator
+ statusMessage(ingText);
+ $('batchactions_go').className = 'loading';
- // Put an AJAXY loading icon on the button
- $('Form_PublishItemsForm_action_publishitems').className = 'loading';
+ // Submit form
Ajax.SubmitForm(this, null, {
onSuccess : function(response) {
Ajax.Evaluator(response);
- $('Form_PublishItemsForm_action_publishitems').className = '';
+ $('batchactions_go').className = '';
treeactions.closeSelection($('batchactions'));
},
onFailure : function(response) {
- errorMessage(ss.i18n._t('CMSMAIN.ERRORPUBLISHING'), response);
+ errorMessage('Error ' + ingText, response);
}
});
} else {
@@ -450,4 +529,4 @@ TreeContextMenu = {
treeNode.onOrderChanged(sortedChildren,treeNode);
}
-};
\ No newline at end of file
+};
diff --git a/javascript/LeftAndMain.js b/javascript/LeftAndMain.js
index 407ffb10..57d90a09 100644
--- a/javascript/LeftAndMain.js
+++ b/javascript/LeftAndMain.js
@@ -886,4 +886,28 @@ function hideIndicator(id) {
setInterval(function() {
new Ajax.Request("Security/ping");
-}, 5*60*1000);
\ No newline at end of file
+}, 5*60*1000);
+
+/**
+ * Find and enable TinyMCE on all htmleditor fields
+ * Pulled in from old tinymce.template.js
+ */
+
+function nullConverter(url) {
+ return url;
+}
+
+Behaviour.register({
+ 'textarea.htmleditor' : {
+ initialize : function() {
+ tinyMCE.execCommand("mceAddControl", true, this.id);
+ this.isChanged = function() {
+ return tinyMCE.getInstanceById(this.id).isDirty();
+ }
+ this.resetChanged = function() {
+ inst = tinyMCE.getInstanceById(this.id);
+ inst.startContent = tinymce.trim(inst.getContent({format : 'raw', no_events : 1}));
+ }
+ }
+ }
+})
diff --git a/javascript/LeftAndMain_left.js b/javascript/LeftAndMain_left.js
index e999f5ad..ff2c9ca8 100755
--- a/javascript/LeftAndMain_left.js
+++ b/javascript/LeftAndMain_left.js
@@ -27,6 +27,48 @@ var TreeContextMenu = null;
*/
TreeAPI = Class.create();
TreeAPI.prototype = {
+
+ setCustomURL: function(url, arguments) {
+ this.customURL = url;
+ this.customArguments = $H(arguments);
+ },
+
+ clearCustomURL: function() {
+ this.customURL = this.customArguments = null;
+ },
+
+ url: function(args) {
+ var args = $H(args).merge(this.customArguments);
+
+ var url = this.customURL ? this.customURL : SiteTreeHandlers.loadTree_url;
+ url = url + (url.match(/\?/) ? '&' : '?') + args.toQueryString();
+
+ console.log('Loading tree from ' + url);
+ return url;
+ },
+
+ reload: function(options) {
+ this.innerHTML = 'Loading...';
+
+ var args = {ajax:1, ID:0};
+ if ($('Form_EditForm_Locale')) args.local = $('Form_EditForm_Locale').value;
+
+ url = this.url(args);
+
+ var self = this;
+ new Ajax.Request(url, {
+ onSuccess: function(response){
+ self.innerHTML = response.responseText;
+ self.castAsTreeNode(self.firstChild);
+ if (options.onSuccess) options.onSuccess(response);
+ },
+ onFailure: function(response){
+ errorMessage('error loading tree', response);
+ if (options.onError) options.onError(response);
+ }
+ });
+ },
+
/**
* Perform the given code on the each tree node with the given index.
* There could be more than one :-)
@@ -177,11 +219,11 @@ TreeNodeAPI.prototype = {
this.cuedNewNodes[this.cuedNewNodes.length] = node;
}
-
- var url = SiteTreeHandlers.loadTree_url;
- url += (url.match(/\?/)) ? '&' : '?';
- url += 'ajax=1&ID=' + this.getIdx();
- if($('Form_EditForm_Locale')) url += "&locale=" + $('Form_EditForm_Locale').value;
+ var args = {ajax:1, ID:this.getIdx()};
+ if ($('Form_EditForm_Locale')) args.local = $('Form_EditForm_Locale').value;
+
+ url = this.tree.url(args);
+
new Ajax.Request(url, {
onSuccess : this.installSubtree.bind(this),
onFailure : this.showSubtreeLoadingError
@@ -481,30 +523,3 @@ ReorganiseAction.prototype = {
}
}
}
-
-/**
- * Control the site tree filter
- */
-SiteTreeFilterForm = Class.create();
-SiteTreeFilterForm.applyTo('form#search_options');
-SiteTreeFilterForm.prototype = {
- onsubmit: function() {
- $('SiteTreeSearchButton').className = 'hidden';
- $('searchIndicator').className = 'loading';
- Ajax.SubmitForm(this, null, {
- onSuccess : function(response) {
- $('SiteTreeIsFiltered').value = 1;
- $('SiteTreeSearchButton').className = '';
- $('searchIndicator').className = '';
- $('sitetree_ul').innerHTML = response.responseText;
- Behaviour.apply($('sitetree_ul'));
- statusMessage('Filtered tree','good');
- },
- onFailure : function(response) {
- errorMessage('Could not filter site tree ' + response.responseText);
- }
- });
-
- return false;
- }
-}
diff --git a/javascript/WidgetAreaEditor.js b/javascript/WidgetAreaEditor.js
index 9d6a2fa7..31fdfcf7 100644
--- a/javascript/WidgetAreaEditor.js
+++ b/javascript/WidgetAreaEditor.js
@@ -1,7 +1,7 @@
-WidgetAreaEditor = Class.create();
-WidgetAreaEditor.applyTo('div.WidgetAreaEditor');
+WidgetAreaEditorClass = Class.create();
+WidgetAreaEditorClass.applyTo('div.WidgetAreaEditor');
-WidgetAreaEditor.prototype = {
+WidgetAreaEditorClass.prototype = {
initialize: function() {
UsedWidget.applyToChildren($('WidgetAreaEditor_usedWidgets'), 'div.Widget');
diff --git a/javascript/tinymce.template.js b/javascript/tinymce.template.js
deleted file mode 100755
index ffef4da9..00000000
--- a/javascript/tinymce.template.js
+++ /dev/null
@@ -1,63 +0,0 @@
-function nullConverter(url) {
- return url;
-}
-
-/**
- * TinyMCE initialisation template.
- * $ variables are replaced by string search & replace. It's pretty crude.
- */
-// Prevents "Error: 'tinyMCE' is undefined" error in IE7 on Newsletter Recipient import.
-if((typeof tinyMCE != 'undefined')) {
- tinyMCE.init({
- mode : "none",
- language: "$Lang",
- width: "100%",
- auto_resize : false,
- theme : "advanced",
- content_css : "cms/css/editor.css, $ContentCSS",
- body_class : 'typography',
- document_base_url: "$BaseURL",
- urlconverter_callback : "nullConverter",
-
- setupcontent_callback : "sapphiremce_setupcontent",
- cleanup_callback : "sapphiremce_cleanup",
-
- theme_advanced_layout_manager: "SimpleLayout",
- theme_advanced_toolbar_location : "top",
- theme_advanced_toolbar_align : "left",
- theme_advanced_toolbar_parent : "right",
- plugins : "media,contextmenu,table,emotions,paste,../../tinymce_ssbuttons,../../tinymce_advcode,spellchecker,fullscreen",
- blockquote_clear_tag : "p",
- table_inline_editing : true,
- theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,separator,bullist,numlist,outdent,indent,blockquote,hr,charmap",
- theme_advanced_buttons2 : "undo,redo,separator,cut,copy,paste,pastetext,pasteword,spellchecker,separator,ssimage,ssflash,sslink,unlink,anchor,separator,advcode,fullscreen,separator,search,replace,selectall,visualaid",
- theme_advanced_buttons3 : "tablecontrols",
- spellchecker_languages : "$SpellcheckLangs",
-
- template_templates : [
- { title : "Three column", src : "assets/snippet.html", description : "A simple 3 column layout"},
- ],
-
- safari_warning : false,
- relative_urls : true,
- verify_html : true,
- use_native_selects : true, // fancy selects are bug as of SS 2.3.0
- valid_elements : "+a[id|rel|rev|dir|tabindex|accesskey|type|name|href|target|title|class],-strong/-b[class],-em/-i[class],-strike[class],-u[class],#p[id|dir|class|align],-ol[class],-ul[class],-li[class],br,img[id|dir|longdesc|usemap|class|src|border|alt=|title|width|height|align],-sub[class],-sup[class],-blockquote[dir|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|dir|id|style],-tr[id|dir|class|rowspan|width|height|align|valign|bgcolor|background|bordercolor|style],tbody[id|class|style],thead[id|class|style],tfoot[id|class|style],-td[id|dir|class|colspan|rowspan|width|height|align|valign|scope|style],-th[id|dir|class|colspan|rowspan|width|height|align|valign|scope|style],caption[id|dir|class],-div[id|dir|class|align|style],-span[class|align],-pre[class|align],address[class|align],-h1[id|dir|class|align],-h2[id|dir|class|align],-h3[id|dir|class|align],-h4[id|dir|class|align],-h5[id|dir|class|align],-h6[id|dir|class|align],hr[class],dd[id|class|title|dir],dl[id|class|title|dir],dt[id|class|title|dir]",
- extended_valid_elements : "img[class|src|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name|usemap],iframe[src|name|width|height|align|frameborder|marginwidth|marginheight|scrolling],object[width|height|data|type],param[name|value],map[class|name|id],area[shape|coords|href|target|alt]"
- });
-}
-
-Behaviour.register({
- 'textarea.htmleditor' : {
- initialize : function() {
- tinyMCE.execCommand("mceAddControl", true, this.id);
- this.isChanged = function() {
- return tinyMCE.getInstanceById(this.id).isDirty();
- }
- this.resetChanged = function() {
- inst = tinyMCE.getInstanceById(this.id);
- inst.startContent = tinymce.trim(inst.getContent({format : 'raw', no_events : 1}));
- }
- }
- }
-})
diff --git a/lang/en_US.php b/lang/en_US.php
index 93499386..9bfb1ece 100755
--- a/lang/en_US.php
+++ b/lang/en_US.php
@@ -150,7 +150,7 @@ $lang['en_US']['CMSMain']['WORKTODO'] = 'You have work to do on these %d
$lang['en_US']['CMSMain_dialog.ss']['BUTTONNOTFOUND'] = 'Couldn\'t find the button name';
$lang['en_US']['CMSMain_dialog.ss']['NOLINKED'] = 'Can\'t find window.linkedObject to send the button click back to the main window';
$lang['en_US']['CMSMain_left.ss']['ADDEDNOTPUB'] = 'Added to the draft site and not published yet';
-$lang['en_US']['CMSMain_left.ss']['ADDSEARCHCRITERIA'] = 'Add Criteria...';
+$lang['en_US']['CMSMain_left.ss']['ADDSEARCHCRITERIA'] = 'Add Criteria';
$lang['en_US']['CMSMain_left.ss']['BATCHACTIONS'] = array(
'Batch Actions',
PR_HIGH
@@ -177,6 +177,7 @@ $lang['en_US']['CMSMain_left.ss']['NEW'] = 'new';
$lang['en_US']['CMSMain_left.ss']['OPENBOX'] = 'click to open this box';
$lang['en_US']['CMSMain_left.ss']['PAGEVERSIONH'] = 'Page Version History';
$lang['en_US']['CMSMain_left.ss']['PUBLISHCONFIRM'] = 'Publish the selected pages';
+$lang['en_US']['CMSMain_left.ss']['CLEAR'] = 'Clear';
$lang['en_US']['CMSMain_left.ss']['SEARCH'] = array(
'Search',
PR_HIGH
diff --git a/templates/Includes/CMSMain_left.ss b/templates/Includes/CMSMain_left.ss
index d78659c4..7a4d7c0a 100755
--- a/templates/Includes/CMSMain_left.ss
+++ b/templates/Includes/CMSMain_left.ss
@@ -29,15 +29,19 @@