mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
Trac 6981: Opt-in URL Updating
This commit is contained in:
parent
dedb9d0461
commit
bd94c6f336
@ -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')),
|
||||
|
@ -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; }
|
||||
|
@ -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 = $('<span />', {
|
||||
'id': 'URLSegmentHolder'
|
||||
});
|
||||
|
||||
// edit button
|
||||
editAction = $('<button />', {
|
||||
'id': 'Form_EditForm_URLSegment_Edit',
|
||||
'class': 'ss-ui-button',
|
||||
'text': 'Edit',
|
||||
'click': function(e) {
|
||||
e.preventDefault();
|
||||
self.edit();
|
||||
}
|
||||
});
|
||||
|
||||
// update button
|
||||
updateAction = $('<button />', {
|
||||
'id': 'Form_EditForm_URLSegment_Update',
|
||||
'text': 'OK',
|
||||
'click': function(e) {
|
||||
e.preventDefault();
|
||||
self.update();
|
||||
}
|
||||
});
|
||||
|
||||
// cancel button
|
||||
cancelAction = $('<a />', {
|
||||
'id': 'Form_EditForm_URLSegment_Cancel',
|
||||
'href': '#',
|
||||
'text': 'cancel',
|
||||
'click': function(e) {
|
||||
e.preventDefault();
|
||||
self.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
// insert elements
|
||||
holder.insertAfter('.URLPrefix');
|
||||
editAction.insertAfter(self);
|
||||
cancelAction.insertAfter(self);
|
||||
updateAction.insertAfter(self);
|
||||
},
|
||||
|
||||
/**
|
||||
* Function: _autoInputWidth
|
||||
*
|
||||
* Sets the width of input so it lines up with the other fields
|
||||
*
|
||||
*/
|
||||
_autoInputWidth: function() {
|
||||
var self = this,
|
||||
prefix_width,
|
||||
new_width;
|
||||
|
||||
prefix_width = $('.URLPrefix').width();
|
||||
new_width = ((self.width() + 9) - prefix_width);
|
||||
self.width(new_width);
|
||||
}
|
||||
});
|
||||
|
||||
@ -82,12 +245,20 @@
|
||||
// Constructor: onmatch
|
||||
onmatch : function() {
|
||||
var self = this;
|
||||
|
||||
var URLSegment = $('.cms-edit-form input[name=URLSegment]');
|
||||
var LiveURLSegment = $('.cms-edit-form input[name=LiveURLSegment]');
|
||||
|
||||
this.bind('change', function(e) {
|
||||
self.updatePageTitleHeading();
|
||||
self.updateURLSegment(jQuery('.cms-edit-form input[name=URLSegment]'));
|
||||
// TODO We should really user-confirm these changes
|
||||
self.parents('form').find('input[name=MetaTitle], input[name=MenuTitle]').val(self.val());
|
||||
// Criteria for defining a "new" page
|
||||
if ( (URLSegment.val().indexOf("new") == 0) && LiveURLSegment.val() == "" ) {
|
||||
self.updatePageTitleHeading();
|
||||
self.parents('form').find('input[name=MetaTitle], input[name=MenuTitle]').val(self.val());
|
||||
// update the URLSegment
|
||||
URLSegment.update(self);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
this._super();
|
||||
@ -100,32 +271,6 @@
|
||||
*/
|
||||
updatePageTitleHeading: function() {
|
||||
$('#page-title-heading').text(this.val());
|
||||
},
|
||||
|
||||
/**
|
||||
* Function: updateURLSegment
|
||||
*
|
||||
* Parameters:
|
||||
* (DOMElement) field
|
||||
*/
|
||||
updateURLSegment: function(field) {
|
||||
if(!field || !field.length) return;
|
||||
|
||||
// TODO The new URL value is determined asynchronously,
|
||||
// which means we need to come up with an alternative system
|
||||
// to ask user permission to change it.
|
||||
|
||||
// TODO language/logic coupling
|
||||
var isNew = this.val().indexOf("new") == 0;
|
||||
var confirmMessage = ss.i18n._t(
|
||||
'UPDATEURL.CONFIRMSIMPLE',
|
||||
'Do you want to update the URL from your new page title?'
|
||||
);
|
||||
|
||||
// don't ask for replacement if record is considered 'new' as defined by its title
|
||||
if(isNew || confirm(confirmMessage)) {
|
||||
field.val(this.val()).trigger('change');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -85,4 +85,35 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** ------------------------------------------------------------------
|
||||
* URLSegment field
|
||||
* ----------------------------------------------------------------- */
|
||||
.URLPrefix,
|
||||
.URLSegmentHolder {
|
||||
padding-top: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.URLPrefix {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
#Form_EditForm_URLSegment {
|
||||
margin-left: 7px;
|
||||
|
||||
&.disabled {
|
||||
color: #444;
|
||||
padding-left: 0px;
|
||||
margin-left: 0px;
|
||||
background: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
#Form_EditForm_URLSegment_Cancel,
|
||||
#Form_EditForm_URLSegment_Update,
|
||||
#Form_EditForm_URLSegment_Edit {
|
||||
margin-left: 7px;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<span>$URLPrefix</span> <input $AttributesHTML />
|
||||
<span class="URLPrefix">$URLPrefix</span><input $AttributesHTML />
|
||||
<% if HelpText %>
|
||||
<p class="help">$HelpText</p>
|
||||
<% end_if %>
|
Loading…
Reference in New Issue
Block a user