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);