diff --git a/code/CMSMain.php b/code/CMSMain.php
index 78c815f0..d75b6556 100755
--- a/code/CMSMain.php
+++ b/code/CMSMain.php
@@ -55,31 +55,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'SiteTreeAsUL',
'getshowdeletedsubtree',
'getfilteredsubtree',
- 'batchactions'
+ 'batchactions',
+ 'SearchTreeForm'
);
- /**
- * SiteTree Columns that can be filtered using the the Site Tree Search button
- */
- static $site_tree_filter_options = array(
- 'Title' => array('CMSMain.TITLE', 'Title'),
- 'MenuTitle' => array('CMSMain.MENUTITLE', 'Navigation Label'),
- 'ClassName' => array('CMSMain.PAGETYPE', 'Page Type'),
- 'Status' => array('CMSMain.STATUS', 'Status'),
- 'MetaDescription' => array('CMSMain.METADESC', 'Description'),
- 'MetaKeywords' => array('CMSMain.METAKEYWORDS', 'Keywords')
- );
-
- static function T_SiteTreeFilterOptions(){
- 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'),
- '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();
@@ -155,15 +134,17 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
*
* @return string
*/
- public function getfilteredsubtree() {
- // Sanity and security checks
- if (!isset($_REQUEST['filter'])) die('No filter passed');
- if (!ClassInfo::exists($_REQUEST['filter'])) die ('That filter class does not exist');
- if (!is_subclass_of($_REQUEST['filter'], 'CMSSiteTreeFilter')) die ('That is not a valid filter');
+ public function getfilteredsubtree($data, $form) {
+ $params = $form->getData();
- // Do eeet!
- $filter = new $_REQUEST['filter']();
- return $filter->getTree();
+ // Get the tree
+ $tree = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID'], null, array(new CMSMainMarkingFilter($params), 'mark'));
+
+ // Trim off the outer tag
+ $tree = ereg_replace('^[ \t\r\n]*
]*>','', $tree);
+ $tree = ereg_replace('
]*>[ \t\r\n]*$','', $tree);
+
+ return $tree;
}
/**
@@ -188,32 +169,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return $doSet;
}
- /**
- * Returns the SiteTree columns that can be filtered using the the Site Tree Search button as a DataObjectSet
- */
- public function SiteTreeFilterOptions() {
- $filter_options = new DataObjectSet();
- foreach(self::T_SiteTreeFilterOptions() as $key => $value) {
- $record = array(
- 'Column' => $key,
- 'Title' => $value,
- );
- $filter_options->push(new ArrayData($record));
- }
- return $filter_options;
- }
- public function SiteTreeFilterDateField() {
- $dateField = new CalendarDateField('SiteTreeFilterDate');
- return $dateField->Field();
- }
- public function SiteTreeFilterPageTypeField() {
- $types = SiteTree::page_type_classes(); array_unshift($types, 'All');
- $source = array_combine($types, $types);
- asort($source);
- $optionsetField = new DropdownField('ClassName', 'ClassName', $source, 'Any');
- return $optionsetField->Field();
- }
-
public function generateDataTreeHints() {
$classes = ClassInfo::subclassesFor( $this->stat('tree_class') );
@@ -1095,6 +1050,61 @@ JS;
return new Form($this, "AddPageOptionsForm", $fields, $actions);
}
+
+ /**
+ * Form used to filter the sitetree. It can only be used via javascript for now.
+ *
+ * @return Form
+ */
+ function SearchTreeForm() {
+ // get all page types in a dropdown-compatible format
+ $pageTypes = SiteTree::page_type_classes();
+ array_unshift($pageTypes, 'All');
+ $pageTypes = array_combine($pageTypes, $pageTypes);
+ asort($pageTypes);
+
+ $form = new Form(
+ $this,
+ 'SearchTreeForm',
+ new FieldSet(
+ new TextField(
+ 'Title',
+ _t('CMSMain.TITLEOPT', 'Title')
+ ),
+ new TextField('Content', 'Text'),
+ new CalendarDateField('EditedSince', _t('CMSMain_left.ss.EDITEDSINCE','Edited Since')),
+ new DropdownField('ClassName', 'Page Type', $pageTypes, null, 'Any'),
+ new TextField(
+ 'MenuTitle',
+ _t('CMSMain.MENUTITLEOPT', 'Navigation Label')
+ ),
+ new TextField(
+ 'Status',
+ _t('CMSMain.STATUSOPT', 'Status')
+ ),
+ new TextField(
+ 'MetaDescription',
+ _t('CMSMain.METADESCOPT', 'Description')
+ ),
+ new TextField(
+ 'MetaKeywords',
+ _t('CMSMain.METAKEYWORDSOPT', 'Keywords')
+ )
+ ),
+ new FieldSet(
+ new ResetFormAction(
+ 'clear',
+ _t('CMSMain_left.ss.CLEAR', 'Clear')
+ ),
+ new FormAction(
+ 'getfilteredsubtree',
+ _t('CMSMain_left.ss.SEARCH', 'Search')
+ )
+ )
+ );
+
+ return $form;
+ }
/**
* Helper function to get page count
@@ -1330,36 +1340,46 @@ JS;
class CMSMainMarkingFilter {
- function __construct() {
+ /**
+ * @var array Request params (unsanitized)
+ */
+ protected $params = array();
+
+ /**
+ * @param array $params Request params (unsanitized)
+ */
+ function __construct($params = null) {
$this->ids = array();
$this->expanded = array();
+ $this->params = $params;
$where = array();
- // Match against URLSegment, Title, MenuTitle & Content
- if (isset($_REQUEST['SiteTreeSearchTerm'])) {
- $term = Convert::raw2sql($_REQUEST['SiteTreeSearchTerm']);
- $where[] = "\"URLSegment\" LIKE '%$term%' OR \"Title\" LIKE '%$term%' OR \"MenuTitle\" LIKE '%$term%' OR \"Content\" LIKE '%$term%'";
- }
-
- // Match against date
- if (isset($_REQUEST['SiteTreeFilterDate'])) {
- $date = $_REQUEST['SiteTreeFilterDate'];
- $date = ((int)substr($date,6,4)) . '-' . ((int)substr($date,3,2)) . '-' . ((int)substr($date,0,2));
- $where[] = "\"LastEdited\" > '$date'";
- }
-
- // Match against exact ClassName
- if (isset($_REQUEST['ClassName']) && $_REQUEST['ClassName'] != 'All') {
- $klass = Convert::raw2sql($_REQUEST['ClassName']);
- $where[] = "\"ClassName\" = '$klass'";
- }
-
- // Partial string match against a variety of fields
- foreach (CMSMain::T_SiteTreeFilterOptions() as $key => $value) {
- if (!empty($_REQUEST[$key])) {
- $match = Convert::raw2sql($_REQUEST[$key]);
- $where[] = "\"$key\" LIKE '%$match%'";
+ $SQL_params = Convert::raw2sql($this->params);
+ foreach($SQL_params as $name => $val) {
+ switch($name) {
+ // Match against URLSegment, Title, MenuTitle & Content
+ case 'SiteTreeSearchTerm':
+ $where[] = "\"URLSegment\" LIKE '%$val%' OR \"Title\" LIKE '%$val%' OR \"MenuTitle\" LIKE '%$val%' OR \"Content\" LIKE '%$val%'";
+ break;
+ // Match against date
+ case 'SiteTreeFilterDate':
+ $val = ((int)substr($val,6,4))
+ . '-' . ((int)substr($val,3,2))
+ . '-' . ((int)substr($val,0,2));
+ $where[] = "\"LastEdited\" > '$val'";
+ break;
+ // Match against exact ClassName
+ case 'ClassName':
+ if($val != 'All') {
+ $where[] = "\"ClassName\" = '$val'";
+ }
+ break;
+ default:
+ // Partial string match against a variety of fields
+ if(!empty($val) && singleton("SiteTree")->hasDatabaseField($name)) {
+ $where[] = "\"$name\" LIKE '%$val%'";
+ }
}
}
diff --git a/code/LeftAndMain.php b/code/LeftAndMain.php
index f646867e..1b0f6817 100644
--- a/code/LeftAndMain.php
+++ b/code/LeftAndMain.php
@@ -294,9 +294,6 @@ class LeftAndMain extends Controller {
'cms/javascript/SideReports.js',
'cms/javascript/LangSelector.js',
'cms/javascript/TranslationTab.js',
- 'jsparty/calendar/calendar.js',
- 'jsparty/calendar/lang/calendar-en.js',
- 'jsparty/calendar/calendar-setup.js',
)
);
diff --git a/css/cms_left.css b/css/cms_left.css
index 6fb1035b..8e4b00e0 100644
--- a/css/cms_left.css
+++ b/css/cms_left.css
@@ -384,25 +384,19 @@ ul.tree span.untranslated a:visited {
color: #ccc
}
-#left form.actionparams div.SearchCriteria {
- width: 28%;
- overflow: hidden;
- float: left;
-}
-
-#left form.actionparams input.SearchCriteria, #left form.actionparams #InputSiteTreeFilterClassName select {
+#Form_SearchTreeForm .field .middleColumn {
width: 60%;
float: left;
margin: 0;
}
-#left form.actionparams #InputSiteTreeFilterDate .calendar {
- margin-left: -96px;
- width: 190px;
- height: 141px;
+
+#Form_SearchTreeForm .field label {
+ margin-left: 0;
+ width: 28%;
}
-/* IE7 fix: */
-#left form.actionparams #InputSiteTreeFilterDate table {
- width: 70%;
+
+#Form_SearchTreeForm select.options {
+ clear: left;
}
/* Change detection CSS */
diff --git a/javascript/CMSMain.js b/javascript/CMSMain.js
index 881dcc95..ba948143 100644
--- a/javascript/CMSMain.js
+++ b/javascript/CMSMain.js
@@ -205,5 +205,118 @@
});
}
}});
+
+ /**
+ * Control the site tree filter.
+ */
+ $('#Form_SearchTreeForm').concrete('ss.searchTreeForm', function($) {return{
+
+ SelectEl: null,
+
+ onmatch: function() {
+ var self = this;
+
+ // TODO Cant bind to onsubmit/onreset directly because of IE6
+ this.bind('submit', function(e) {return self.submitForm(e);});
+ this.bind('reset', function(e) {return self.resetForm(e);});
+
+ // only the first field should be visible by default
+ this.find('.field').not(':first').hide();
+
+ // generate the field dropdown
+ this.setSelectEl($('')
+ .appendTo(this.find('fieldset:first'))
+ .bind('change', function(e) {self.addField(e);})
+ );
+
+ this._setOptions();
+
+ },
+
+ _setOptions: function() {
+ var self = this;
+
+ // reset existing elements
+ self.SelectEl().find('option').remove();
+
+ // add default option
+ // TODO i18n
+ $('').appendTo(self.SelectEl())
+
+ // populate dropdown values from existing fields
+ this.find('.field').each(function() {
+ $('').appendTo(self.SelectEl())
+ .val(this.id)
+ .text($(this).find('label').text());
+ });
+ },
+
+ submitForm: function(e) {
+ var self = this;
+ var data = [];
+ // convert from jQuery object literals to hash map
+ $(this.serializeArray()).each(function(i, el) {
+ data[el.name] = el.value;
+ });
+
+ // Set new URL
+ $('#sitetree')[0].setCustomURL(this.attr('action') + '&action_getfilteredsubtree=1', data);
+
+ // Disable checkbox tree controls that currently don't work with search.
+ // @todo: Make them work together
+ if ($('#sitetree')[0].isDraggable) $('#sitetree')[0].stopBeingDraggable();
+ $('.checkboxAboveTree :checkbox').val(false).attr('disabled', true);
+
+ // disable buttons to avoid multiple submission
+ //this.find(':submit').attr('disabled', true);
+
+ this.find(':submit[name=action_getfilteredsubtree]').addClass('loading');
+
+ $('#sitetree')[0].reload({
+ onSuccess : function(response) {
+ console.debug(self);
+ console.debug(self.find(':submit'));
+ self.find(':submit').attr('disabled', false).removeClass('loading');
+ statusMessage('Filtered tree','good');
+ },
+ onFailure : function(response) {
+ self.find(':submit').attr('disabled', false).removeClass('loading');
+ errorMessage('Could not filter site tree ' + response.responseText);
+ }
+ });
+
+ return false;
+ },
+
+ resetForm: function(e) {
+ this.find('.field').clearFields().not(':first').val('').hide();
+
+ // Reset URL to default
+ $('#sitetree')[0].clearCustomURL();
+
+ // Enable checkbox tree controls
+ $('.checkboxAboveTree :checkbox').attr('disabled', 'false');
+
+ // reset all options, some of the might be removed
+ this._setOptions();
+
+ return false;
+ },
+
+ addField: function(e) {
+ var $select = $(e.target);
+ // show formfield matching the option
+ this.find('#' + $select.val()).show();
+
+ // remove option from dropdown, each field should just exist once
+ this.find('option[value=' + $select.val() + ']').remove();
+
+ // jump back to default entry
+ $select.val(0);
+
+ return false;
+ }
+ }});
+
})(jQuery);
\ No newline at end of file
diff --git a/javascript/CMSMain_left.js b/javascript/CMSMain_left.js
index 7ea18dcf..048d0f68 100755
--- a/javascript/CMSMain_left.js
+++ b/javascript/CMSMain_left.js
@@ -153,93 +153,7 @@ SiteTreeFilter.prototype = {
});
}
}
-/**
- * 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);};
- });
- },
- onsubmit: function() {
- var filters = $H();
-
- if (this.clicked == 'Clear') {
- Form.getElements(this).each(function(el){
- if (el.type == 'text') el.value = '';
- else if (el.type == 'select-one') el.value = 'All';
- });
- document.getElementsBySelector('.SearchCriteriaContainer', this).each(function(el){
- Element.hide(el);
- })
- }
- else {
- 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);
- }
- });
- }
-
- if (filters.keys().length) {
- // Set new URL
- $('sitetree').setCustomURL(SiteTreeHandlers.controller_url + '/getfilteredsubtree?filter=CMSSiteTreeFilter_Search', 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
- */
-SiteTreeFilterAddCriteria = Class.create();
-SiteTreeFilterAddCriteria.applyTo('#SiteTreeFilterAddCriteria');
-SiteTreeFilterAddCriteria.prototype = {
- onchange : function() {
- Element.show('Container' + this.value);
- // Element.show('Text' + this.value);
- // Element.show('Input' + this.value);
- this.selectedIndex = 0; //reset selected criteria to prompt
- }
-}
/**
* Batch Actions button click action
diff --git a/templates/Includes/CMSMain_TreeTools.ss b/templates/Includes/CMSMain_TreeTools.ss
index 3cc4d884..83edd26b 100644
--- a/templates/Includes/CMSMain_TreeTools.ss
+++ b/templates/Includes/CMSMain_TreeTools.ss
@@ -32,44 +32,7 @@