mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
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:
commit
b394c8b9db
@ -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
|
||||||
|
@ -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,6 +604,10 @@ 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();
|
||||||
|
|
||||||
@ -622,8 +616,12 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
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;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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>
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user