Merge branch 'linking-fixes-3.0' of git://github.com/silverstripe-droptables/sapphire into silverstripe-droptables-linking-fixes-3.0

This commit is contained in:
Ingo Schommer 2012-07-12 17:27:18 +02:00
commit b394c8b9db
4 changed files with 38 additions and 40 deletions

View File

@ -63,14 +63,14 @@ class HtmlEditorField extends TextareaField {
if($links = $value->getElementsByTagName('a')) foreach($links as $link) { if($links = $value->getElementsByTagName('a')) foreach($links as $link) {
$matches = array(); $matches = array();
if(preg_match('/\[sitetree_link id=([0-9]+)\]/i', $link->getAttribute('href'), $matches)) { if(preg_match('/\[sitetree_link(?:\s*|%20|,)?id=([0-9]+)\]/i', $link->getAttribute('href'), $matches)) {
if(!DataObject::get_by_id('SiteTree', $matches[1])) { if(!DataObject::get_by_id('SiteTree', $matches[1])) {
$class = $link->getAttribute('class'); $class = $link->getAttribute('class');
$link->setAttribute('class', ($class ? "$class ss-broken" : 'ss-broken')); $link->setAttribute('class', ($class ? "$class ss-broken" : 'ss-broken'));
} }
} }
if(preg_match('/\[file_link id=([0-9]+)\]/i', $link->getAttribute('href'), $matches)) { if(preg_match('/\[file_link(?:\s*|%20|,)?id=([0-9]+)\]/i', $link->getAttribute('href'), $matches)) {
if(!DataObject::get_by_id('File', $matches[1])) { if(!DataObject::get_by_id('File', $matches[1])) {
$class = $link->getAttribute('class'); $class = $link->getAttribute('class');
$link->setAttribute('class', ($class ? "$class ss-broken" : 'ss-broken')); $link->setAttribute('class', ($class ? "$class ss-broken" : 'ss-broken'));
@ -114,7 +114,7 @@ class HtmlEditorField extends TextareaField {
$href = Director::makeRelative($link->getAttribute('href')); $href = Director::makeRelative($link->getAttribute('href'));
if($href) { if($href) {
if(preg_match('/\[sitetree_link id=([0-9]+)\]/i', $href, $matches)) { if(preg_match('/\[sitetree_link,id=([0-9]+)\]/i', $href, $matches)) {
$ID = $matches[1]; $ID = $matches[1];
// clear out any broken link classes // clear out any broken link classes

View File

@ -468,7 +468,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
* which are toggled through a type dropdown. Variations share fields, so there's only one "title" field in the form. * which are toggled through a type dropdown. Variations share fields, so there's only one "title" field in the form.
*/ */
$('form.htmleditorfield-linkform').entwine({ $('form.htmleditorfield-linkform').entwine({
// TODO Entwine doesn't respect submits triggered by ENTER key // TODO Entwine doesn't respect submits triggered by ENTER key
onsubmit: function(e) { onsubmit: function(e) {
this.insertLink(); this.insertLink();
@ -477,36 +476,27 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
}, },
resetFields: function() { resetFields: function() {
this._super(); this._super();
this.find('fieldset :input:not(:radio)').val('').change();
// Reset the form using a native call. This will also correctly reset checkboxes and radio buttons.
this[0].reset();
}, },
redraw: function(setDefaults) { redraw: function() {
this._super(); this._super();
var linkType = this.find(':input[name=LinkType]:checked').val(), list = ['internal', 'external', 'file', 'email']; var linkType = this.find(':input[name=LinkType]:checked').val(), list = ['internal', 'external', 'file', 'email'];
// If we haven't selected an existing link, then just make sure we default to "internal" for the link type.
if(!linkType) {
this.find(':input[name=LinkType]').val(['internal']);
linkType = 'internal';
}
this.addAnchorSelector(); this.addAnchorSelector();
// Toggle field visibility and state based on type selection // Toggle field visibility depending on the link type.
this.find('div.content .field').hide(); this.find('div.content .field').hide();
this.find('.field#LinkType').show(); this.find('.field#LinkType').show();
this.find('.field#' + linkType).show(); this.find('.field#' + linkType).show();
if(linkType == 'internal' || linkType == 'anchor') this.find('.field#Anchor').show(); if(linkType == 'internal' || linkType == 'anchor') this.find('.field#Anchor').show();
if(linkType !== 'email') this.find('.field#TargetBlank').show();
if(linkType == 'anchor') { if(linkType == 'anchor') {
this.find('.field#AnchorSelector').show(); this.find('.field#AnchorSelector').show();
this.find('.field#AnchorRefresh').show(); this.find('.field#AnchorRefresh').show();
} }
this.find(':input[name=TargetBlank]').attr('disabled', (linkType == 'email'));
if(typeof setDefaults == 'undefined' || setDefaults) {
this.find(':input[name=TargetBlank]').attr('checked', (linkType == 'file'));
}
}, },
insertLink: function() { insertLink: function() {
var href, target = null, anchor = this.find(':input[name=Anchor]').val(); var href, target = null, anchor = this.find(':input[name=Anchor]').val();
@ -614,16 +604,24 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
selector.append($('<option value="'+anchors[j]+'">'+anchors[j]+'</option>')); selector.append($('<option value="'+anchors[j]+'">'+anchors[j]+'</option>'));
} }
}, },
/**
* Updates the state of the dialog inputs to match the editor selection.
* If selection does not contain a link, resets the fields.
*/
updateFromEditor: function() { updateFromEditor: function() {
var htmlTagPattern = /<\S[^><]*>/g, fieldName, data = this.getCurrentLink(); var htmlTagPattern = /<\S[^><]*>/g, fieldName, data = this.getCurrentLink();
if(data) { if(data) {
for(fieldName in data) { for(fieldName in data) {
var el = this.find(':input[name=' + fieldName + ']'), selected = data[fieldName]; var el = this.find(':input[name=' + fieldName + ']'), selected = data[fieldName];
// Remove html tags in the selected text that occurs on IE browsers // Remove html tags in the selected text that occurs on IE browsers
if(typeof(selected) == 'string') selected = selected.replace(htmlTagPattern, ''); if(typeof(selected) == 'string') selected = selected.replace(htmlTagPattern, '');
if(el.is(':radio')) {
el.val([selected]).change(); // setting as an arry due to jQuery quirks // Set values and invoke the triggers (e.g. for TreeDropdownField).
if(el.is(':checkbox')) {
el.prop('checked', selected).change();
} else if(el.is(':radio')) {
el.val([selected]).change();
} else { } else {
el.val(selected).change(); el.val(selected).change();
} }
@ -631,8 +629,9 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
} }
}, },
/** /**
* Return information about the currently selected link, suitable for population of the link * Return information about the currently selected link, suitable for population of the link form.
* form. *
* Returns null if no link was currently selected.
*/ */
getCurrentLink: function() { getCurrentLink: function() {
var selectedEl = this.getSelection(), var selectedEl = this.getSelection(),
@ -682,7 +681,8 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
return { return {
LinkType: 'file', LinkType: 'file',
file: RegExp.$1, file: RegExp.$1,
Description: title Description: title,
TargetBlank: target ? true : false
}; };
} else if(href.match(/^#(.*)$/)) { } else if(href.match(/^#(.*)$/)) {
return { return {
@ -691,7 +691,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
Description: title, Description: title,
TargetBlank: target ? true : false TargetBlank: target ? true : false
}; };
} else if(href.match(/^\[sitetree_link\s*(?:%20)?id=([0-9]+)\]?(#.*)?$/)) { } else if(href.match(/^\[sitetree_link(?:\s*|%20|,)?id=([0-9]+)\]?(#.*)?$/i)) {
return { return {
LinkType: 'internal', LinkType: 'internal',
internal: RegExp.$1, internal: RegExp.$1,
@ -707,9 +707,8 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
TargetBlank: target ? true : false TargetBlank: target ? true : false
}; };
} else { } else {
return { // No link/invalid link selected.
LinkType: 'internal' return null;
};
} }
} }
}); });

View File

@ -29,7 +29,7 @@
* @todo Expand title height to fit all elements * @todo Expand title height to fit all elements
*/ */
$('.TreeDropdownField').entwine({ $('.TreeDropdownField').entwine({
onmatch: function() { onadd: function() {
this.append( this.append(
'<span class="treedropdownfield-title"></span>' + '<span class="treedropdownfield-title"></span>' +
'<div class="treedropdownfield-toggle-panel-link"><a href="#" class="ui-icon ui-icon-triangle-1-s"></a></div>' + '<div class="treedropdownfield-toggle-panel-link"><a href="#" class="ui-icon ui-icon-triangle-1-s"></a></div>' +
@ -43,9 +43,6 @@
this.getPanel().hide(); this.getPanel().hide();
this._super(); this._super();
}, },
onunmatch: function() {
this._super();
},
getPanel: function() { getPanel: function() {
return this.find('.treedropdownfield-panel'); return this.find('.treedropdownfield-panel');
}, },
@ -260,7 +257,7 @@
}); });
$('.TreeDropdownField.searchable').entwine({ $('.TreeDropdownField.searchable').entwine({
onmatch: function() { onadd: function() {
this._super(); this._super();
var title = this.data('title'); var title = this.data('title');
@ -270,9 +267,6 @@
this.setTitle(title ? title : strings.searchFieldTitle); this.setTitle(title ? title : strings.searchFieldTitle);
}, },
onunmatch: function() {
this._super();
},
setTitle: function(title) { setTitle: function(title) {
if(!title && title !== '') title = strings.fieldTitle; if(!title && title !== '') title = strings.fieldTitle;
@ -372,8 +366,13 @@
}); });
$('.TreeDropdownField input[type=hidden]').entwine({ $('.TreeDropdownField input[type=hidden]').entwine({
onchange: function() { onadd: function() {
this.getField().updateTitle(); this.bind('change.TreeDropdownField', function() {
$(this).getField().updateTitle();
});
},
onremove: function() {
this.unbind('.TreeDropdownField');
} }
}); });
}); });

View File

@ -29,7 +29,7 @@
* *
* <b>Inbuilt Shortcodes</b> * <b>Inbuilt Shortcodes</b>
* *
* From 2.4 onwards links inserted via the CMS into a content field are in the form ''<a href="[sitetree_link id=n]">''. At runtime this is replaced by a plain link to the page with the ID in question. * From 2.4 onwards links inserted via the CMS into a content field are in the form ''<a href="[sitetree_link id=n]">'', and from 3.0 the comma is used as a separator instead ''<a href="[sitetree_link,id=n]">''. At runtime this is replaced by a plain link to the page with the ID in question.
* *
* <b>Limitations</b> * <b>Limitations</b>
* *