From bd94c6f33634282a74ff8d0b0209e4c30126fe30 Mon Sep 17 00:00:00 2001 From: Ryan Wachtl Date: Wed, 9 May 2012 19:01:57 -0500 Subject: [PATCH 1/2] Trac 6981: Opt-in URL Updating --- code/model/SiteTree.php | 2 +- css/screen.css | 49 ++++ javascript/CMSMain.EditForm.js | 251 ++++++++++++++++----- scss/_CMSMain.scss | 31 +++ templates/forms/SiteTreeURLSegmentField.ss | 2 +- 5 files changed, 280 insertions(+), 55 deletions(-) diff --git a/code/model/SiteTree.php b/code/model/SiteTree.php index 04a2ab82..3c6eac83 100644 --- a/code/model/SiteTree.php +++ b/code/model/SiteTree.php @@ -1835,11 +1835,11 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid $rootTab = new TabSet("Root", $tabMain = new Tab('Main', new TextField("Title", $this->fieldLabel('Title')), + $urlsegment, new TextField("MenuTitle", $this->fieldLabel('MenuTitle')), $htmlField = new HtmlEditorField("Content", _t('SiteTree.HTMLEDITORTITLE', "Content", 'HTML editor title')) ), $tabMeta = new Tab('Metadata', - $urlsegment, new TextField("MetaTitle", $this->fieldLabel('MetaTitle')), new TextareaField("MetaKeywords", $this->fieldLabel('MetaKeywords'), 1), new TextareaField("MetaDescription", $this->fieldLabel('MetaDescription')), diff --git a/css/screen.css b/css/screen.css index 447de452..5f9d1053 100644 --- a/css/screen.css +++ b/css/screen.css @@ -3,42 +3,91 @@ /** ----------------------------- CMS Components ------------------------------ */ /** Style custom to the CMSMain admin interface. CMSMain extends the built in SilverStripe admin section styles. As much as possible we want to use those built in styles. If anything in this file can be implemented in a generic way then it should be include in the admin scss files. @package cms */ /** ------------------------------------------------------------------ Page History Section. ----------------------------------------------------------------- */ +/* line 15, ../scss/_CMSMain.scss */ #cms-page-history-versions tr.loading { color: #999; } +/* line 20, ../scss/_CMSMain.scss */ #cms-page-history-versions tr.loading td:hover { cursor: none; } +/* line 27, ../scss/_CMSMain.scss */ #cms-page-history-versions td:hover { cursor: pointer; } +/* line 34, ../scss/_CMSMain.scss */ .CMSPageHistoryController ins { background-color: #DFD; padding: 2px; text-decoration: none; } +/* line 40, ../scss/_CMSMain.scss */ .CMSPageHistoryController del { background-color: #FDD; padding: 2px; color: #ff4444; } /** -------------------------------------------- Tree View (collapsed for sidebar) -------------------------------------------- */ +/* line 51, ../scss/_CMSMain.scss */ #cms-content-treeview .cms-tree-expand-trigger { display: none; } +/* line 58, ../scss/_CMSMain.scss */ .cms-content-tools #cms-content-treeview .cms-content-toolbar { border-bottom: none; box-shadow: none; margin-bottom: 8px; } +/* line 62, ../scss/_CMSMain.scss */ .cms-content-tools #cms-content-treeview .cms-content-toolbar .cms-page-add-button { margin-top: 8px; } +/* line 67, ../scss/_CMSMain.scss */ .cms-content-tools #cms-content-treeview .cms-tree-view-modes, .cms-content-tools #cms-content-treeview .cms-content-batchactions { display: none; } +/* line 70, ../scss/_CMSMain.scss */ .cms-content-tools #cms-content-treeview .cms-tree-expand-trigger { display: inline-block; margin: 0 0 2px 0; position: absolute; top: 8px; right: 4px; } +/* line 76, ../scss/_CMSMain.scss */ .cms-content-tools #cms-content-treeview .cms-tree-expand-trigger span.ui-button-text { padding-right: 8px; } +/* line 83, ../scss/_CMSMain.scss */ .cms-content-tools #cms-content-treeview .cms-tree .badge, .cms-content-tools #cms-content-treeview .cms-tree a > .jstree-icon { display: none; } +/** ------------------------------------------------------------------ URLSegment field ----------------------------------------------------------------- */ +/* line 94, ../scss/_CMSMain.scss */ +.URLPrefix, .URLSegmentHolder { padding-top: 8px; display: inline-block; } + +/* line 99, ../scss/_CMSMain.scss */ +.URLPrefix { color: #777; } + +/* line 103, ../scss/_CMSMain.scss */ +#Form_EditForm_URLSegment { margin-left: 7px; } +/* line 106, ../scss/_CMSMain.scss */ +#Form_EditForm_URLSegment.disabled { color: #444; padding-left: 0px; margin-left: 0px; background: none; border-color: transparent; } + +/* line 117, ../scss/_CMSMain.scss */ +#Form_EditForm_URLSegment_Cancel, #Form_EditForm_URLSegment_Update, #Form_EditForm_URLSegment_Edit { margin-left: 7px; } + +/* line 2, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-fields { overflow: hidden; } +/* line 4, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-fields .cms-edit-form.AssetAdmin { overflow-y: auto; } +/* line 7, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-fields .cms-content-tools .cms-panel-content { overflow: hidden; } +/* line 9, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-fields .cms-content-tools .cms-panel-content .cms-search-form { height: 100%; } +/* line 17, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav li a { font-weight: bold; line-height: 16px; padding: 12px 20px 12px; text-indent: -9999em; } +/* line 23, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav li a.content-treeview { background: url(../images/content-header-tabs-sprite.png) no-repeat 2px 0px; } +/* line 26, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav li a.content-galleryview { background: url(../images/content-header-tabs-sprite.png) no-repeat -160px 0px; } +/* line 29, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav li a.content-listview { background: url(../images/content-header-tabs-sprite.png) no-repeat -39px 0px; } +/* line 37, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-state-active, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active { border-top: none; } +/* line 43, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-state-active a.content-treeview, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active a.content-treeview, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active a.content-treeview { background: url(../images/content-header-tabs-sprite.png) no-repeat 1px -40px; } +/* line 46, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-state-active a.content-galleryview, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active a.content-galleryview, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active a.content-galleryview { background: url(../images/content-header-tabs-sprite.png) no-repeat -161px -40px; } +/* line 49, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-state-active a.content-listview, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active a.content-listview, .cms .AssetAdmin .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active a.content-listview { background: url(../images/content-header-tabs-sprite.png) no-repeat -38px -40px; } +/* line 58, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-toolbar .cms-page-add-button { background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f3f3f3), color-stop(100%, #d9d9d9)); background-image: -webkit-linear-gradient(#f3f3f3, #d9d9d9); background-image: -moz-linear-gradient(#f3f3f3, #d9d9d9); background-image: -o-linear-gradient(#f3f3f3, #d9d9d9); background-image: -ms-linear-gradient(#f3f3f3, #d9d9d9); background-image: linear-gradient(#f3f3f3, #d9d9d9); border-color: #c0c0c2; } +/* line 61, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-toolbar .cms-page-add-button span.btn-icon-add { height: 17px; } +/* line 64, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin .cms-content-toolbar .cms-page-add-button span.ui-button-text { color: #393939; text-shadow: white 0 1px 1px; } +/* line 72, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin #Root_TreeView .cms-tree ul .class-Folder a span.text span.jstree-foldericon { background: url(../images/blue-folder-horizontal.png) no-repeat; width: 16px; height: 16px; float: left; display: block; margin-right: 4px; } +/* line 83, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin #Form_EditForm_File td { padding-top: 0; padding-bottom: 0; } +/* line 87, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin #Form_EditForm_File td.bottom-all { padding: 0.7em; } +/* line 91, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin #Form_EditForm_File td.col-StripThumbnail { padding: 0; width: 32px; height: 32px; display: block; } +/* line 97, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin #Form_EditForm_File td.col-StripThumbnail img { width: 32px; height: 32px; } +/* line 103, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin #Form_EditForm_File tr[data-class=Folder] td.col-StripThumbnail { background: transparent url(../images/treeicons/blue-folder-horizontal.png) no-repeat top left; } +/* line 108, ../scss/_AssetAdmin.scss */ .cms .AssetAdmin #Form_EditForm_File tr[data-class=File] td.col-StripThumbnail { background: transparent url(../images/treeicons/blue-document.png) no-repeat top left; } diff --git a/javascript/CMSMain.EditForm.js b/javascript/CMSMain.EditForm.js index 4b143cdf..f7728291 100644 --- a/javascript/CMSMain.EditForm.js +++ b/javascript/CMSMain.EditForm.js @@ -27,31 +27,118 @@ */ onmatch : function() { var self = this; - - // intercept change event, do our own writing - this.bind('change', function(e) { - if(!self.val()) return; - - self.addClass('disabled').parents('.field:first').addClass('loading'); - var oldVal = self.val(); - self.suggest(oldVal, function(data) { - self.removeClass('disabled').parents('.field:first').removeClass('loading'); - var newVal = decodeURIComponent(data.value); - self.val(newVal); - - if(oldVal != newVal) { - var confirmMessage = ss.i18n.sprintf( - ss.i18n._t('UPDATEURL.CONFIRMURLCHANGED', 'The URL has been changed to\n"%s'), - data.value - ); - jQuery.noticeAdd({'text':confirmMessage}); - } - }); - - }); + + // add elements and actions for editing + self._addActions(); + // toggle + self.edit(); + // set width of input field + self._autoInputWidth(); this._super(); }, + + /** + * Function: edit + * + * Toggles the edit state of the field + * + * Return URLSegemnt val() + * + * Parameters: + * (Bool) external (optional) + */ + edit: function(external) { + + var self = this, + holder = $('#URLSegmentHolder'), + edit = $('#Form_EditForm_URLSegment_Edit'), + update = $('#Form_EditForm_URLSegment_Update'), + cancel = $('#Form_EditForm_URLSegment_Cancel'); + + // transfer current value to holder + holder.text(self.val()); + + // toggle elements + if (self.is(':visible')) { + update.hide(); + cancel.hide(); + self.hide(); + holder.show(); + edit.show(); + } else { + edit.hide(); + holder.hide(); + self.show(); + update.show(); + cancel.show(); + } + + // field updated from another fields value + // reset to original state + if (external) { + self.edit(); + } + + return self.val(); + }, + + /** + * Function: update + * + * Commits the change of the URLSegment to the field + * Optional: pass in another element to use its value + * to update the URLSegment (ex. from Title) + * + * Parameters: + * (jQuery Wrapped DOM element) field (optional) + */ + update: function(field) { + + var self = this, + holder = $('#URLSegmentHolder'), + currentVal = holder.text(), + updateVal, + external = null; + + if (field && field.val() != "") { + updateVal = field.val(); + external = true; + } else { + updateVal = self.val(); + } + + if (currentVal != updateVal) { + + self.suggest(updateVal, function(data) { + var newVal = decodeURIComponent(data.value); + self.val(newVal); + self.edit(external); + }); + + } else { + + self.edit(); + } + }, + + /** + * Function: cancel + * + * Cancels any changes to the field + * + * Return URLSegemnt val() + * + */ + cancel: function() { + + var self = this, + holder = $('#URLSegmentHolder'); + self.val(holder.text()); + self.edit(); + + return self.val(); + }, /** * Function: suggest @@ -63,13 +150,89 @@ * (Function) callback */ suggest: function(val, callback) { + $.get( this.parents('form:first').attr('action') + - '/field/URLSegment/suggest/?value=' + encodeURIComponent(this.val()), + '/field/URLSegment/suggest/?value=' + encodeURIComponent(val), function(data) { callback.apply(this, arguments); } ); + + }, + + /** + * Function: _addActions + * + * Utility to add edit buttons and actions + * + */ + _addActions: function() { + + var self = this, + holder, + editAction, + updateAction, + cancelAction; + + // element to display non-editable text + holder = $('', { + 'id': 'URLSegmentHolder' + }); + + // edit button + editAction = $('