mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-21 01:41:46 +03:00
d8728aad57
issue #5841 - fix relative link checks in navlink url input component - fix navlink url input component sending absolute URLs instead of relative URLs to action handler - remove URL manipulation in navigation settings controller (url input handles URL manipulation, validator flags anything that's still incorrect) - capture cmd-s in url input to ensure changes are actioned before save - automatically add mailto: to e-mail addresses - add gh-validation-state-container component so .error/.success validation classes can be applied to any container element - add validation-state mixin that can be mixed in to any other component to give it access to validation status (used in gh-navitem component to keep alignment when inline error message elements are added) - validate and display inline errors on save - improve ember test coverage for navigation settings related controller and components
127 lines
3.5 KiB
JavaScript
127 lines
3.5 KiB
JavaScript
import Ember from 'ember';
|
|
|
|
var joinUrlParts,
|
|
isRelative;
|
|
|
|
joinUrlParts = function (url, path) {
|
|
if (path[0] !== '/' && url.slice(-1) !== '/') {
|
|
path = '/' + path;
|
|
} else if (path[0] === '/' && url.slice(-1) === '/') {
|
|
path = path.slice(1);
|
|
}
|
|
|
|
return url + path;
|
|
};
|
|
|
|
isRelative = function (url) {
|
|
// "protocol://", "//example.com", "scheme:", "#anchor", & invalid paths
|
|
// should all be treated as absolute
|
|
return !url.match(/\s/) && !validator.isURL(url) && !url.match(/^(\/\/|#|[a-zA-Z0-9\-]+:)/);
|
|
};
|
|
|
|
export default Ember.TextField.extend({
|
|
classNames: 'gh-input',
|
|
classNameBindings: ['fakePlaceholder'],
|
|
|
|
didReceiveAttrs: function () {
|
|
var url = this.get('url'),
|
|
baseUrl = this.get('baseUrl');
|
|
|
|
// if we have a relative url, create the absolute url to be displayed in the input
|
|
if (isRelative(url)) {
|
|
url = joinUrlParts(baseUrl, url);
|
|
}
|
|
|
|
this.set('value', url);
|
|
},
|
|
|
|
isBaseUrl: Ember.computed('baseUrl', 'value', function () {
|
|
return this.get('baseUrl') === this.get('value');
|
|
}),
|
|
|
|
fakePlaceholder: Ember.computed('isBaseUrl', 'hasFocus', function () {
|
|
return this.get('isBaseUrl') && this.get('last') && !this.get('hasFocus');
|
|
}),
|
|
|
|
focusIn: function (event) {
|
|
this.set('hasFocus', true);
|
|
|
|
if (this.get('isBaseUrl')) {
|
|
// position the cursor at the end of the input
|
|
Ember.run.next(function (el) {
|
|
var length = el.value.length;
|
|
|
|
el.setSelectionRange(length, length);
|
|
}, event.target);
|
|
}
|
|
},
|
|
|
|
keyDown: function (event) {
|
|
// delete the "placeholder" value all at once
|
|
if (this.get('isBaseUrl') && (event.keyCode === 8 || event.keyCode === 46)) {
|
|
this.set('value', '');
|
|
|
|
event.preventDefault();
|
|
}
|
|
|
|
// CMD-S
|
|
if (event.keyCode === 83 && event.metaKey) {
|
|
this.notifyUrlChanged();
|
|
}
|
|
},
|
|
|
|
keyPress: function (event) {
|
|
// enter key
|
|
if (event.keyCode === 13) {
|
|
event.preventDefault();
|
|
this.notifyUrlChanged();
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
focusOut: function () {
|
|
this.set('hasFocus', false);
|
|
|
|
this.notifyUrlChanged();
|
|
},
|
|
|
|
notifyUrlChanged: function () {
|
|
this.set('value', this.get('value').trim());
|
|
|
|
var url = this.get('value'),
|
|
urlParts = document.createElement('a'),
|
|
baseUrl = this.get('baseUrl'),
|
|
baseUrlParts = document.createElement('a');
|
|
|
|
// leverage the browser's native URI parsing
|
|
urlParts.href = url;
|
|
baseUrlParts.href = baseUrl;
|
|
|
|
// if we have an email address, add the mailto:
|
|
if (validator.isEmail(url)) {
|
|
url = `mailto:${url}`;
|
|
this.set('value', url);
|
|
}
|
|
|
|
// if we have a relative url, create the absolute url to be displayed in the input
|
|
if (isRelative(url)) {
|
|
url = joinUrlParts(baseUrl, url);
|
|
this.set('value', url);
|
|
}
|
|
|
|
// remove the base url before sending to action
|
|
if (urlParts.host === baseUrlParts.host && !url.match(/^#/)) {
|
|
url = url.replace(/^[a-zA-Z0-9\-]+:/, '');
|
|
url = url.replace(/^\/\//, '');
|
|
url = url.replace(baseUrlParts.host, '');
|
|
url = url.replace(baseUrlParts.pathname, '');
|
|
if (!url.match(/^\//)) {
|
|
url = '/' + url;
|
|
}
|
|
}
|
|
|
|
this.sendAction('change', url);
|
|
}
|
|
});
|