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:
Ingo Schommer 2012-05-10 11:59:15 +02:00
commit 526120d949
5 changed files with 241 additions and 55 deletions

View File

@ -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')),

View File

@ -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; }

View File

@ -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');
}
} }
}); });

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
<span>$URLPrefix</span>&nbsp;<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 %>