From 21361df3bebc209ac39b2a7b311c98891b099a09 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Tue, 14 Mar 2017 16:37:47 +0000 Subject: [PATCH] Revert "Multi line title (#575)" This reverts commit 989ad7b9c1e1586eddeb3a0051bb6d0a2fce1800. --- ghost/admin/app/components/gh-title.js | 95 ------------------- ghost/admin/app/styles/app.css | 2 +- ghost/admin/app/styles/components/title.css | 24 ----- ghost/admin/app/styles/layouts/main.css | 1 + .../app/templates/components/gh-title.hbs | 1 - ghost/admin/app/templates/editor/edit.hbs | 24 +---- .../gh-koenig/addon/components/gh-koenig.js | 55 ----------- ghost/admin/tests/acceptance/editor-test.js | 20 ++-- ghost/admin/tests/helpers/editor-helpers.js | 15 --- .../integration/components/gh-title-test.js | 24 ----- 10 files changed, 9 insertions(+), 252 deletions(-) delete mode 100644 ghost/admin/app/components/gh-title.js delete mode 100644 ghost/admin/app/styles/components/title.css delete mode 100644 ghost/admin/app/templates/components/gh-title.hbs delete mode 100644 ghost/admin/tests/integration/components/gh-title-test.js diff --git a/ghost/admin/app/components/gh-title.js b/ghost/admin/app/components/gh-title.js deleted file mode 100644 index f4c23747bf..0000000000 --- a/ghost/admin/app/components/gh-title.js +++ /dev/null @@ -1,95 +0,0 @@ -import Component from 'ember-component'; - -export default Component.extend({ - _cachedValue: '', - _mutationObserver: null, - tagName: 'h2', - didRender() { - if (this._rendered) { - return; - } - - let title = this.$('div'); - if (!this.get('value')) { - title.addClass('no-content'); - } - title[0].onkeydown = (event) => { - // block the browser format keys. - if (event.ctrlKey || event.metaKey) { - switch (event.keyCode) { - case 66: // B - case 98: // b - case 73: // I - case 105: // i - case 85: // U - case 117: // u - return false; - } - } - if (event.keyCode === 13) { - // enter - return false; - } - - // down key - // if we're within ten pixels of the bottom of this element then we try and figure out where to position - // the cursor in the editor. - if (event.keyCode === 40) { - let range = window.getSelection().getRangeAt(0); // get the actual range within the DOM. - let cursorPositionOnScreen = range.getBoundingClientRect(); - let offset = title.offset(); - let bottomOfHeading = offset.top + title.height(); - if (cursorPositionOnScreen.bottom > bottomOfHeading - 33) { - let {editor} = window; // hmmm, this is nasty! - // We need to pass the editor instance so that we can `this.get('editor');` - // but the editor instance is within the component and not exposed. - // there's also a dependency that the editor will have with the title and the title will have with the editor - // so that the cursor can move both ways (up and down) between them. - // see `lib/gh-koenig/addon/gh-koenig.js` and the function `findCursorPositionFromPixel` which should actually be - // encompassed here. - let loc = editor.element.getBoundingClientRect(); - - let cursorPositionInEditor = editor.positionAtPoint(cursorPositionOnScreen.left, loc.top); - - if (cursorPositionInEditor.isBlank) { - editor.element.focus(); - } else { - editor.selectRange(cursorPositionInEditor.toRange()); - } - return false; - } - } - title.removeClass('no-content'); - }; - - // setup mutation observer - let mutationObserver = new MutationObserver(() => { - // on mutate we update. - if (title[0].textContent !== '') { - title.removeClass('no-content'); - } else { - title.addClass('no-content'); - } - - // sanity check if there is formatting reset it. - let {textContent} = title[0]; // eslint-disable-line - if (title[0].innerHTML !== textContent && title[0].innerHTML) { - title[0].innerHTML = textContent; - // todo: retain the range position. - } - - if (this.get('_cachedValue') !== textContent) { - this.set('_cacheValue', textContent); - this.sendAction('onChange', textContent); - this.sendAction('update', textContent); - } - }); - - mutationObserver.observe(title[0], {childList: true, characterData: true, subtree: true}); - this.set('_mutationObserver', mutationObserver); - this.set('_rendered', true); - }, - willDestroyElement() { - this.get('_mutationObserver').disconnect(); - } -}); diff --git a/ghost/admin/app/styles/app.css b/ghost/admin/app/styles/app.css index 059a985393..1d76f2220f 100644 --- a/ghost/admin/app/styles/app.css +++ b/ghost/admin/app/styles/app.css @@ -31,7 +31,7 @@ @import "components/selectize.css"; @import "components/power-select.css"; @import "components/publishmenu.css"; -@import "components/title.css"; + /* Layouts: Groups of Components /* ---------------------------------------------------------- */ diff --git a/ghost/admin/app/styles/components/title.css b/ghost/admin/app/styles/components/title.css deleted file mode 100644 index 273dec40a1..0000000000 --- a/ghost/admin/app/styles/components/title.css +++ /dev/null @@ -1,24 +0,0 @@ -.gh-title { - padding:0 0 0 1px; /* need some left padding otherwise the cursor isn't visible on the left hand side */ - margin:0; - outline:none; - position:relative; - width:100%; - letter-spacing:0.8px; - font-weight: bold; - font-size: 3.2rem; - line-height: 3.2em; -} - -/* Place holder content that displays in the title if it is empty */ -.gh-title.no-content:after { - content: attr(data-placeholder); - color: #bbb; - cursor: text; - position:absolute; - top:0; - font-size: 3.2rem; - line-height: 3.2em; - font-weight: bold; - min-width: 30rem; /* hack it's defaulting just to enough width for the 'Your' in 'Your Post Title' */ -} diff --git a/ghost/admin/app/styles/layouts/main.css b/ghost/admin/app/styles/layouts/main.css index f49f51aae0..0c6b492971 100644 --- a/ghost/admin/app/styles/layouts/main.css +++ b/ghost/admin/app/styles/layouts/main.css @@ -489,6 +489,7 @@ body > .ember-view:not(.default-liquid-destination) { margin: 0; padding: 0; text-overflow: ellipsis; + white-space: nowrap; font-size: 2rem; line-height: 1.2em; font-weight: 400; diff --git a/ghost/admin/app/templates/components/gh-title.hbs b/ghost/admin/app/templates/components/gh-title.hbs deleted file mode 100644 index 305485a30d..0000000000 --- a/ghost/admin/app/templates/components/gh-title.hbs +++ /dev/null @@ -1 +0,0 @@ -
{{value}}
\ No newline at end of file diff --git a/ghost/admin/app/templates/editor/edit.hbs b/ghost/admin/app/templates/editor/edit.hbs index 5af5b8e622..e39d5546aa 100644 --- a/ghost/admin/app/templates/editor/edit.hbs +++ b/ghost/admin/app/templates/editor/edit.hbs @@ -34,29 +34,8 @@
- {{#gh-view-title classNames="gh-editor-title" openMobileMenu="openMobileMenu"}} - {{gh-title - value=(readonly model.titleScratch) - onChange=(action (mut model.titleScratch)) - tabindex="1" - shouldFocus=shouldFocusTitle - focus-out="updateTitle" - update=(action (perform updateTitle)) - keyDown=(action "titleKeyDown") - id='gh-title' - }} - + {{gh-trim-focus-input model.titleScratch type="text" id="entry-title" placeholder="Your Post Title" tabindex="1" shouldFocus=shouldFocusTitle focus-out="updateTitle" update=(action (perform updateTitle)) keyDown=(action "titleKeyDown")}} {{/gh-view-title}} {{#if scheduleCountdown}}
diff --git a/ghost/admin/lib/gh-koenig/addon/components/gh-koenig.js b/ghost/admin/lib/gh-koenig/addon/components/gh-koenig.js index e4952cef98..122c122bac 100644 --- a/ghost/admin/lib/gh-koenig/addon/components/gh-koenig.js +++ b/ghost/admin/lib/gh-koenig/addon/components/gh-koenig.js @@ -7,7 +7,6 @@ import {MOBILEDOC_VERSION} from 'mobiledoc-kit/renderers/mobiledoc'; import createCardFactory from '../lib/card-factory'; import defaultCommands from '../options/default-commands'; import editorCards from '../cards/index'; -import $ from 'jquery'; // import { VALID_MARKUP_SECTION_TAGNAMES } from 'mobiledoc-kit/models/markup-section'; //the block elements supported by mobile-doc export const BLANK_DOC = { @@ -118,30 +117,6 @@ export default Component.extend({ this.editor.cursorDidChange(() => this.cursorMoved()); - // hack to track key up to focus back on the title when the up key is pressed - this.editor.element.addEventListener('keydown', (event) => { - if (event.keyCode === 38) { - let range = window.getSelection().getRangeAt(0); // get the actual range within the DOM. - let cursorPositionOnScreen = range.getBoundingClientRect(); - let topOfEditor = this.editor.element.getBoundingClientRect().top; - if (cursorPositionOnScreen.top < topOfEditor + 33) { - let $title = $(this.titleQuery); - - // let offset = findCursorPositionFromPixel($title[0].firstChild, cursorPositionOnScreen.left); - - // let newRange = document.createRange(); - // newRange.collapse(true); - // newRange.setStart($title[0].firstChild, offset); - // newRange.setEnd($title[0].firstChild, offset); - // updateCursor(newRange); - - $title[0].focus(); - - return false; - } - } - }); - }, // drag and drop images onto the editor @@ -174,33 +149,3 @@ export default Component.extend({ } }); - -// // code for moving the cursor into the correct position of the title: (is buggy) - -// // find the cursor position based on a pixel offset of an element. -// // used to move the cursor vertically into the title. -// function findCursorPositionFromPixel(el, horizontal_offset) { -// let len = el.textContent.length; -// let range = document.createRange(); -// for(let i = len -1; i > -1; i--) { -// range.setStart(el, i); -// range.setEnd(el, i + 1); -// let rect = range.getBoundingClientRect(); -// if (rect.top === rect.bottom) { -// continue; -// } -// if(rect.left <= horizontal_offset && rect.right >= horizontal_offset) { -// return i + (horizontal_offset >= (rect.left + rect.right) / 2 ? 1 : 0); // if the horizontal_offset is on the left hand side of the -// // character then return `i`, if it's on the right return `i + 1` -// } -// } - -// return el.length; -// } - -// // update the cursor position. -// function updateCursor(range) { -// let selection = window.getSelection(); -// selection.removeAllRanges(); -// selection.addRange(range); -// } diff --git a/ghost/admin/tests/acceptance/editor-test.js b/ghost/admin/tests/acceptance/editor-test.js index 2858e3579d..81af1ab964 100644 --- a/ghost/admin/tests/acceptance/editor-test.js +++ b/ghost/admin/tests/acceptance/editor-test.js @@ -12,7 +12,7 @@ import {invalidateSession, authenticateSession} from 'ghost-admin/tests/helpers/ import Mirage from 'ember-cli-mirage'; import sinon from 'sinon'; import testSelector from 'ember-test-selectors'; -import {titleRendered} from '../helpers/editor-helpers'; + describe('Acceptance: Editor', function() { let application; @@ -25,7 +25,7 @@ describe('Acceptance: Editor', function() { }); it('redirects to signin when not authenticated', function () { - server.create('user'); // necesary for post-author association + server.create('user'); // necessray for post-author association server.create('post'); invalidateSession(application); @@ -397,18 +397,10 @@ describe('Acceptance: Editor', function() { .to.equal('/editor/1'); }); - andThen(() => { - titleRendered(); - }); - - andThen(() => { - let title = find('#gh-title div'); - title.html(Array(160).join('a')); - }); - - andThen(() => { - click('.gh-btn.gh-btn-sm.js-publish-button'); - }); + // Test title validation + fillIn('input[id="entry-title"]', Array(160).join('a')); + triggerEvent('input[id="entry-title"]', 'blur'); + click('.gh-btn.gh-btn-sm.js-publish-button'); andThen(() => { expect( diff --git a/ghost/admin/tests/helpers/editor-helpers.js b/ghost/admin/tests/helpers/editor-helpers.js index 4dfbe01fd4..f000b3fd80 100644 --- a/ghost/admin/tests/helpers/editor-helpers.js +++ b/ghost/admin/tests/helpers/editor-helpers.js @@ -15,21 +15,6 @@ export function editorRendered() { }); } -// polls the title until it's started. -export function titleRendered() { - return Ember.Test.promise(function (resolve) { // eslint-disable-line - function checkTitle() { - let title = $('#gh-title div'); - if (title[0]) { - return resolve(); - } else { - window.requestAnimationFrame(checkTitle); - } - } - checkTitle(); - }); -} - // simulates text inputs into the editor, unfortunately the helper Ember helper functions // don't work on content editable so we have to manipuate the text input event manager // in mobiledoc-kit directly. This is a private API. diff --git a/ghost/admin/tests/integration/components/gh-title-test.js b/ghost/admin/tests/integration/components/gh-title-test.js deleted file mode 100644 index 9207f548d1..0000000000 --- a/ghost/admin/tests/integration/components/gh-title-test.js +++ /dev/null @@ -1,24 +0,0 @@ -import {expect} from 'chai'; -import {describe, it} from 'mocha'; -import {setupComponentTest} from 'ember-mocha'; -import hbs from 'htmlbars-inline-precompile'; - -describe('Integration | Component | gh title', function() { - setupComponentTest('gh-title', { - integration: true - }); - - it('renders', function() { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.on('myAction', function(val) { ... }); - // Template block usage: - // this.render(hbs` - // {{#gh-title}} - // template content - // {{/gh-title}} - // `); - - this.render(hbs`{{gh-title}}`); - expect(this.$()).to.have.length(1); - }); -});