diff --git a/core/client/assets/sass/layouts/post-settings-menu.scss b/core/client/assets/sass/layouts/post-settings-menu.scss index 73b34dc642..20fa8fa5a2 100644 --- a/core/client/assets/sass/layouts/post-settings-menu.scss +++ b/core/client/assets/sass/layouts/post-settings-menu.scss @@ -87,6 +87,9 @@ max-height: 250px; } + .word-count { + font-weight: bold; + } } diff --git a/core/client/components/gh-input.js b/core/client/components/gh-input.js new file mode 100644 index 0000000000..88dc5b6ddc --- /dev/null +++ b/core/client/components/gh-input.js @@ -0,0 +1,5 @@ +import TextInputMixin from 'ghost/mixins/text-input'; + +var Input = Ember.TextField.extend(TextInputMixin); + +export default Input; diff --git a/core/client/components/gh-textarea.js b/core/client/components/gh-textarea.js new file mode 100644 index 0000000000..fbbe45ea26 --- /dev/null +++ b/core/client/components/gh-textarea.js @@ -0,0 +1,5 @@ +import TextInputMixin from 'ghost/mixins/text-input'; + +var TextArea = Ember.TextArea.extend(TextInputMixin); + +export default TextArea; diff --git a/core/client/controllers/post-settings-menu.js b/core/client/controllers/post-settings-menu.js index 50403a4909..2136a5cde1 100644 --- a/core/client/controllers/post-settings-menu.js +++ b/core/client/controllers/post-settings-menu.js @@ -97,6 +97,38 @@ var PostSettingsMenuController = Ember.ObjectController.extend({ }); }, + metaTitleValue: boundOneWay('meta_title'), + + metaDescriptionValue: boundOneWay('meta_description'), + metaDescriptionPlaceholder: Ember.computed('scratch', function () { + var html = this.get('scratch'), + placeholder; + + // Strip HTML + placeholder = $('
', { html: html }).text(); + // Replace new lines and trim + placeholder = placeholder.replace(/\n+/g, ' ').trim(); + // Limit to 156 characters + placeholder = placeholder.substring(0,156); + + return placeholder; + }), + + seoTitle: Ember.computed('titleScratch', 'metaTitleValue', function () { + var metaTitle = this.get('metaTitleValue') || ''; + + return metaTitle.length > 0 ? metaTitle : this.get('titleScratch'); + }), + + seoDescription: Ember.computed('scratch', 'metaDescriptionValue', function () { + var metaDescription = this.get('metaDescriptionValue') || ''; + + return metaDescription.length > 0 ? metaDescription : this.get('metaDescriptionPlaceholder'); + }), + + seoSlug: Ember.computed('slug', 'slugPlaceholder', function () { + return this.get('slug') ? this.get('slug') : this.get('slugPlaceholder'); + }), // observe titleScratch, keeping the post's slug in sync // with it until saved for the first time. @@ -274,6 +306,40 @@ var PostSettingsMenuController = Ember.ObjectController.extend({ }); }, + setMetaTitle: function (metaTitle) { + var self = this; + + this.set('meta_title', metaTitle); + + // If this is a new post. Don't save the model. Defer the save + // to the user pressing the save button + if (this.get('isNew')) { + return; + } + + this.get('model').save(this.get('saveOptions')).catch(function (errors) { + self.showErrors(errors); + self.get('model').rollback(); + }); + }, + + setMetaDescription: function (metaDescription) { + var self = this; + + this.set('meta_description', metaDescription); + + // If this is a new post. Don't save the model. Defer the save + // to the user pressing the save button + if (this.get('isNew')) { + return; + } + + this.get('model').save(this.get('saveOptions')).catch(function (errors) { + self.showErrors(errors); + self.get('model').rollback(); + }); + }, + setCoverImage: function (image) { var self = this; diff --git a/core/client/helpers/gh-count-down-characters.js b/core/client/helpers/gh-count-down-characters.js new file mode 100644 index 0000000000..0712177702 --- /dev/null +++ b/core/client/helpers/gh-count-down-characters.js @@ -0,0 +1,17 @@ +var countDownCharacters = Ember.Handlebars.makeBoundHelper(function (content, maxCharacters) { + var el = document.createElement('span'), + length = content ? content.length : 0; + + el.className = 'word-count'; + if (length > maxCharacters) { + el.style.color = '#E25440'; + } else { + el.style.color = '#9E9D95'; + } + + el.innerHTML = length; + + return new Ember.Handlebars.SafeString(el.outerHTML); +}); + +export default countDownCharacters; \ No newline at end of file diff --git a/core/client/components/gh-blur-input.js b/core/client/mixins/text-input.js similarity index 79% rename from core/client/components/gh-blur-input.js rename to core/client/mixins/text-input.js index 84d771a6d2..f080ee2494 100644 --- a/core/client/components/gh-blur-input.js +++ b/core/client/mixins/text-input.js @@ -1,4 +1,4 @@ -var BlurInput = Ember.TextField.extend({ +var BlurField = Ember.Mixin.create({ selectOnClick: false, stopEnterKeyDownPropagation: false, click: function (event) { @@ -6,9 +6,6 @@ var BlurInput = Ember.TextField.extend({ event.currentTarget.select(); } }, - focusOut: function () { - this.sendAction('action', this.get('value')); - }, keyDown: function (event) { // stop event propagation when pressing "enter" // most useful in the case when undesired (global) keyboard shortcuts are getting triggered while interacting @@ -20,4 +17,4 @@ var BlurInput = Ember.TextField.extend({ } }); -export default BlurInput; +export default BlurField; \ No newline at end of file diff --git a/core/client/templates/post-settings-menu.hbs b/core/client/templates/post-settings-menu.hbs index 002f1a6c9b..e680552d0b 100644 --- a/core/client/templates/post-settings-menu.hbs +++ b/core/client/templates/post-settings-menu.hbs @@ -1,5 +1,5 @@ -{{!----for halfdan:{{#gh-tabs-manager selected="showSubview" id="entry-controls" classNameBindings="isNew:unsaved :right-outlet"}}----}} +{{#gh-tabs-manager selected="showSubview" id="entry-controls" classNameBindings="isNew:unsaved :right-outlet"}}{{gh-blog-url}}/author/{{slugValue}}