diff --git a/core/client/components/gh-trim-focus-input.js b/core/client/components/gh-trim-focus-input.js index 7e9b53b30c..c8f9080f63 100644 --- a/core/client/components/gh-trim-focus-input.js +++ b/core/client/components/gh-trim-focus-input.js @@ -11,6 +11,8 @@ var TrimFocusInput = Ember.TextField.extend({ var text = this.$().val(); this.$().val(text.trim()); + + this.sendAction('onFocusOut'); } }); diff --git a/core/client/controllers/post-settings-menu.js b/core/client/controllers/post-settings-menu.js index 91e6234f4a..2b9b1d4a31 100644 --- a/core/client/controllers/post-settings-menu.js +++ b/core/client/controllers/post-settings-menu.js @@ -87,12 +87,12 @@ var PostSettingsMenuController = Ember.ObjectController.extend({ }); }), //Requests slug from title - generateSlugPlaceholder: function () { + generateAndSetSlug: function (destination) { var self = this, title = this.get('titleScratch'); this.get('slugGenerator').generateSlug(title).then(function (slug) { - self.set('slugPlaceholder', slug); + self.set(destination, slug); }); }, @@ -163,13 +163,15 @@ var PostSettingsMenuController = Ember.ObjectController.extend({ // observe titleScratch, keeping the post's slug in sync // with it until saved for the first time. addTitleObserver: function () { - if (this.get('isNew')) { + if (this.get('isNew') || this.get('title') === '(Untitled)') { this.addObserver('titleScratch', this, 'titleObserver'); } }.observes('model'), titleObserver: function () { if (this.get('isNew') && !this.get('title')) { - Ember.run.debounce(this, 'generateSlugPlaceholder', 700); + Ember.run.debounce(this, 'generateAndSetSlug', ['slugPlaceholder'], 700); + } else if (this.get('title') === '(Untitled)') { + Ember.run.debounce(this, 'generateAndSetSlug', ['slug'], 700); } }, slugPlaceholder: Ember.computed(function (key, value) { diff --git a/core/client/mixins/editor-base-controller.js b/core/client/mixins/editor-base-controller.js index 094da3cba3..84ed1bdde4 100644 --- a/core/client/mixins/editor-base-controller.js +++ b/core/client/mixins/editor-base-controller.js @@ -296,6 +296,12 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, { if (this.get('model.isDraft')) { this.send('save', {silent: true, disableNProgress: true}); } + }, + + autoSaveOnce: function () { + if (this.get('isNew')) { + this.send('autoSave'); + } } } }); diff --git a/core/client/templates/editor/edit.hbs b/core/client/templates/editor/edit.hbs index 4946cea1f9..b71d04751e 100644 --- a/core/client/templates/editor/edit.hbs +++ b/core/client/templates/editor/edit.hbs @@ -6,7 +6,7 @@
- {{gh-trim-focus-input type="text" id="entry-title" placeholder="Your Post Title" value=titleScratch tabindex="1" focus=shouldFocusTitle}} + {{gh-trim-focus-input type="text" id="entry-title" placeholder="Your Post Title" value=titleScratch tabindex="1" focus=shouldFocusTitle onFocusOut="autoSaveOnce"}}
diff --git a/core/test/functional/client/app_test.js b/core/test/functional/client/app_test.js index 675685aeee..033ca251cd 100644 --- a/core/test/functional/client/app_test.js +++ b/core/test/functional/client/app_test.js @@ -73,7 +73,7 @@ CasperTest.begin('Can transition to the editor and back', 6, function suite(test }); casper.thenTransitionAndWaitForScreenLoad('editor', function testTransitionToEditor() { - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); + test.assertUrlMatch(/ghost\/editor\//, 'Landed on the correct URL'); test.assertExists('.entry-markdown', 'Ghost editor is present'); test.assertExists('.entry-preview', 'Ghost preview is present'); }); diff --git a/core/test/functional/client/content_test.js b/core/test/functional/client/content_test.js index 80f1adab7c..5738cd34d1 100644 --- a/core/test/functional/client/content_test.js +++ b/core/test/functional/client/content_test.js @@ -62,7 +62,7 @@ CasperTest.begin('Content list shows correct post status', 5, function testStati }); // Select first non-draft, non-static post. Should be second in the list at this stage of testing. - casper.thenClick('.content-list-content li:nth-of-type(2) a'); + casper.thenClick('.content-list-content li:nth-of-type(3) a'); // Test for status of 'Published' casper.then(function checkStatus() { diff --git a/core/test/functional/client/editor_test.js b/core/test/functional/client/editor_test.js index ec8d487640..60adfe7341 100644 --- a/core/test/functional/client/editor_test.js +++ b/core/test/functional/client/editor_test.js @@ -17,27 +17,6 @@ CasperTest.begin('Ghost editor functions correctly', 20, function suite(test) { test.assertExists('.entry-preview', 'Ghost preview is present'); }); - // Part 1: Test saving with no data - title should default - casper.waitForSelector('#entry-title', function then() { - test.assertEvalEquals(function () { - return document.getElementById('entry-title').value; - }, '', 'Title is empty'); - }); - - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.notification-success', function onSuccess() { - test.assert(true, 'Can save with no title.'); - test.assertEvalEquals(function () { - return document.getElementById('entry-title').value; - }, '(Untitled)', 'Title is "(Untitled)"'); - }, function onTimeout() { - test.assert(false, 'Failed to save without a title.'); - }); - - this.thenClick('.js-bb-notification .close'); - - // Part 2: Test saving with data casper.then(function createTestPost() { casper.sendKeys('#entry-title', testPost.title); casper.writeContentToCodeMirror(testPost.html);