diff --git a/ghost/admin/assets/sass/layouts/settings.scss b/ghost/admin/assets/sass/layouts/settings.scss index e9b083e05a..931c794288 100644 --- a/ghost/admin/assets/sass/layouts/settings.scss +++ b/ghost/admin/assets/sass/layouts/settings.scss @@ -412,6 +412,12 @@ width: 100%; } +.navigation-item-url { + .fake-placeholder { + color: lightgrey + } +} + @media (max-width: 600px) { .navigation-item-label { margin-bottom: 5px; diff --git a/ghost/admin/components/gh-navitem-url-input.js b/ghost/admin/components/gh-navitem-url-input.js new file mode 100644 index 0000000000..7708f4f773 --- /dev/null +++ b/ghost/admin/components/gh-navitem-url-input.js @@ -0,0 +1,76 @@ +function joinUrlParts(url, path) { + if (path[0] !== '/' && url.slice(-1) !== '/') { + path = '/' + path; + } else if (path[0] === '/' && url.slice(-1) === '/') { + path = path.slice(1); + } + + return url + path; +} + +var NavItemUrlInputComponent = Ember.TextField.extend({ + classNameBindings: ['fakePlaceholder'], + + 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('hasFocus'); + }), + + isRelative: Ember.computed('value', function () { + return !validator.isURL(this.get('value')); + }), + + didInsertElement: 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 (this.get('isRelative')) { + url = joinUrlParts(baseUrl, url); + } + + this.set('value', url); + this.sendAction('change', this.get('value')); + }, + + 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(); + } + }, + + focusOut: function () { + this.set('hasFocus', false); + this.set('value', this.get('value').trim()); + + var url = this.get('value'), + baseUrl = this.get('baseUrl'); + + if (this.get('isRelative')) { + this.set('value', joinUrlParts(baseUrl, url)); + } + + this.sendAction('change', url); + } +}); + +export default NavItemUrlInputComponent; diff --git a/ghost/admin/components/gh-navitem.js b/ghost/admin/components/gh-navitem.js new file mode 100644 index 0000000000..bb8f995f35 --- /dev/null +++ b/ghost/admin/components/gh-navitem.js @@ -0,0 +1,27 @@ +var NavItemComponent = Ember.Component.extend({ + classNames: 'navigation-item', + + keyPress: function (event) { + // enter key + if (event.keyCode === 13) { + event.preventDefault(); + this.get('controller').send('addItem'); + } + }, + + actions: { + addItem: function () { + this.sendAction('addItem'); + }, + + deleteItem: function (item) { + this.sendAction('deleteItem', item); + }, + + updateUrl: function (value) { + this.sendAction('updateUrl', value, this.get('navItem')); + } + } +}); + +export default NavItemComponent; diff --git a/ghost/admin/controllers/settings/navigation.js b/ghost/admin/controllers/settings/navigation.js index bd2f447958..31f2c43c6a 100644 --- a/ghost/admin/controllers/settings/navigation.js +++ b/ghost/admin/controllers/settings/navigation.js @@ -5,13 +5,19 @@ NavItem = Ember.Object.extend({ label: '', url: '', - isBlank: Ember.computed('label', 'url', function () { - return Ember.isBlank(this.get('label')) && Ember.isBlank(this.get('url')); + isComplete: Ember.computed('label', 'url', function () { + return !(Ember.isBlank(this.get('label')) || Ember.isBlank(this.get('url'))); }) }); NavigationController = Ember.Controller.extend({ - navigationItems: Ember.computed('model.navigation', function () { + blogUrl: Ember.computed('config.blogUrl', function () { + var url = this.get('config.blogUrl'); + + return url.slice(-1) !== '/' ? url + '/' : url; + }), + + navigationItems: Ember.computed('model.navigation', function () { var navItems, lastItem; @@ -26,7 +32,7 @@ NavigationController = Ember.Controller.extend({ }); lastItem = navItems.get('lastObject'); - if (!lastItem || !lastItem.get('isBlank')) { + if (!lastItem || lastItem.get('isComplete')) { navItems.addObject(NavItem.create()); } @@ -50,7 +56,7 @@ NavigationController = Ember.Controller.extend({ var navItems = this.get('navigationItems'), lastItem = navItems.get('lastObject'); - if (lastItem && !lastItem.get('isBlank')) { + if (lastItem && lastItem.get('isComplete')) { navItems.addObject(NavItem.create()); } }, @@ -63,6 +69,20 @@ NavigationController = Ember.Controller.extend({ this.get('navigationItems').removeObject(item); }, + updateUrl: function (url, navItem) { + if (!navItem) { + return; + } + + if (Ember.isBlank(url)) { + navItem.set('url', this.get('blogUrl')); + + return; + } + + navItem.set('url', url); + }, + save: function () { var self = this, navSetting, @@ -74,7 +94,7 @@ NavigationController = Ember.Controller.extend({ var label, url; - if (!item || item.get('isBlank')) { + if (!item || !item.get('isComplete')) { return; } @@ -93,6 +113,11 @@ NavigationController = Ember.Controller.extend({ url = '/' + url; } + // if navItem label is empty and URL is still the default, don't save + if (!label && url === '/') { + return; + } + return {label: label, url: url}; }).compact(); diff --git a/ghost/admin/html/navigation.html b/ghost/admin/html/navigation.html deleted file mode 100644 index 6425e077db..0000000000 --- a/ghost/admin/html/navigation.html +++ /dev/null @@ -1,199 +0,0 @@ - - - -
- -