mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
Merge pull request #122 from ryanwachtl/silverstripe-cms
--- Basic behaviour for opt-in URL updating. URL is auto-generated on initial edit of the page Title after creating a new page. After page Title has been updated; URLSegment, MenuTitle, and MetaTitle are updated manually. Adds edit, ok, and cancel buttons to URLSegment field. Action to "update from Title" and help text not implemented yet. Any feedback welcome and appreciated.
This commit is contained in:
commit
526120d949
@ -1835,11 +1835,11 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
$rootTab = new TabSet("Root",
|
$rootTab = new TabSet("Root",
|
||||||
$tabMain = new Tab('Main',
|
$tabMain = new Tab('Main',
|
||||||
new TextField("Title", $this->fieldLabel('Title')),
|
new TextField("Title", $this->fieldLabel('Title')),
|
||||||
|
$urlsegment,
|
||||||
new TextField("MenuTitle", $this->fieldLabel('MenuTitle')),
|
new TextField("MenuTitle", $this->fieldLabel('MenuTitle')),
|
||||||
$htmlField = new HtmlEditorField("Content", _t('SiteTree.HTMLEDITORTITLE', "Content", 'HTML editor title'))
|
$htmlField = new HtmlEditorField("Content", _t('SiteTree.HTMLEDITORTITLE', "Content", 'HTML editor title'))
|
||||||
),
|
),
|
||||||
$tabMeta = new Tab('Metadata',
|
$tabMeta = new Tab('Metadata',
|
||||||
$urlsegment,
|
|
||||||
new TextField("MetaTitle", $this->fieldLabel('MetaTitle')),
|
new TextField("MetaTitle", $this->fieldLabel('MetaTitle')),
|
||||||
new TextareaField("MetaKeywords", $this->fieldLabel('MetaKeywords'), 1),
|
new TextareaField("MetaKeywords", $this->fieldLabel('MetaKeywords'), 1),
|
||||||
new TextareaField("MetaDescription", $this->fieldLabel('MetaDescription')),
|
new TextareaField("MetaDescription", $this->fieldLabel('MetaDescription')),
|
||||||
|
@ -20,6 +20,16 @@
|
|||||||
.cms-content-tools #cms-content-treeview .cms-tree-expand-trigger span.ui-button-text { padding-right: 8px; }
|
.cms-content-tools #cms-content-treeview .cms-tree-expand-trigger span.ui-button-text { padding-right: 8px; }
|
||||||
.cms-content-tools #cms-content-treeview .cms-tree .badge, .cms-content-tools #cms-content-treeview .cms-tree a > .jstree-icon { display: none; }
|
.cms-content-tools #cms-content-treeview .cms-tree .badge, .cms-content-tools #cms-content-treeview .cms-tree a > .jstree-icon { display: none; }
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------ URLSegment field ----------------------------------------------------------------- */
|
||||||
|
.URLPrefix, .URLSegmentHolder { padding-top: 8px; display: inline-block; }
|
||||||
|
|
||||||
|
.URLPrefix { color: #777; }
|
||||||
|
|
||||||
|
#Form_EditForm_URLSegment { margin-left: 7px; }
|
||||||
|
#Form_EditForm_URLSegment.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; }
|
||||||
|
|
||||||
.cms .AssetAdmin .cms-content-fields { overflow: hidden; }
|
.cms .AssetAdmin .cms-content-fields { overflow: hidden; }
|
||||||
.cms .AssetAdmin .cms-content-fields .cms-edit-form.AssetAdmin { overflow-y: auto; }
|
.cms .AssetAdmin .cms-content-fields .cms-edit-form.AssetAdmin { overflow-y: auto; }
|
||||||
.cms .AssetAdmin .cms-content-fields .cms-content-tools .cms-panel-content { overflow: hidden; }
|
.cms .AssetAdmin .cms-content-fields .cms-content-tools .cms-panel-content { overflow: hidden; }
|
||||||
|
@ -28,31 +28,118 @@
|
|||||||
onmatch : function() {
|
onmatch : function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// intercept change event, do our own writing
|
// add elements and actions for editing
|
||||||
this.bind('change', function(e) {
|
self._addActions();
|
||||||
if(!self.val()) return;
|
// toggle
|
||||||
|
self.edit();
|
||||||
self.addClass('disabled').parents('.field:first').addClass('loading');
|
// set width of input field
|
||||||
var oldVal = self.val();
|
self._autoInputWidth();
|
||||||
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});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
this._super();
|
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
|
* Function: suggest
|
||||||
*
|
*
|
||||||
@ -63,13 +150,89 @@
|
|||||||
* (Function) callback
|
* (Function) callback
|
||||||
*/
|
*/
|
||||||
suggest: function(val, callback) {
|
suggest: function(val, callback) {
|
||||||
|
|
||||||
$.get(
|
$.get(
|
||||||
this.parents('form:first').attr('action') +
|
this.parents('form:first').attr('action') +
|
||||||
'/field/URLSegment/suggest/?value=' + encodeURIComponent(this.val()),
|
'/field/URLSegment/suggest/?value=' + encodeURIComponent(val),
|
||||||
function(data) {
|
function(data) {
|
||||||
callback.apply(this, arguments);
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,11 +246,19 @@
|
|||||||
onmatch : function() {
|
onmatch : function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
var URLSegment = $('.cms-edit-form input[name=URLSegment]');
|
||||||
|
var LiveURLSegment = $('.cms-edit-form input[name=LiveURLSegment]');
|
||||||
|
|
||||||
this.bind('change', function(e) {
|
this.bind('change', function(e) {
|
||||||
|
// Criteria for defining a "new" page
|
||||||
|
if ( (URLSegment.val().indexOf("new") == 0) && LiveURLSegment.val() == "" ) {
|
||||||
self.updatePageTitleHeading();
|
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());
|
self.parents('form').find('input[name=MetaTitle], input[name=MenuTitle]').val(self.val());
|
||||||
|
// update the URLSegment
|
||||||
|
URLSegment.update(self);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._super();
|
this._super();
|
||||||
@ -100,32 +271,6 @@
|
|||||||
*/
|
*/
|
||||||
updatePageTitleHeading: function() {
|
updatePageTitleHeading: function() {
|
||||||
$('#page-title-heading').text(this.val());
|
$('#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');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,3 +86,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------
|
||||||
|
* 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 %>
|
<% if HelpText %>
|
||||||
<p class="help">$HelpText</p>
|
<p class="help">$HelpText</p>
|
||||||
<% end_if %>
|
<% end_if %>
|
Loading…
Reference in New Issue
Block a user