Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
✨ improved card selection behaviour (#608)
Browse files Browse the repository at this point in the history
Refs: TryGhost/Ghost#8191
Refs: TryGhost/Ghost#8194

Changes the selection behaviour of mobiledoc-cards:
If you navigate to a card with a keyboard or click on the new editor toolbar it "hard selects".
If you click into the body of a card to edit it it "soft selects".

When a card is "hard selected" you can navigate out of the card and to the previous or following blocks within the mobiledoc with the keyboard, you can delete the current card with the backspace or delete button, and you can create a new block following the card with the enter key.

When a card is soft selected it is simply displayed as selected and allows the user to edit content within the card.

New card toolbar:
Allows a user to delete the card, save the card, and "hard select" a card.

New title behaviour:
Pressing the enter key within the title "splits" the title at the cursor point, if multiple characters are selected they are first deleted, and creates a new paragraph at the top of the document with the trailing characters after the split.

gh-cm-editor updates:
Adds an on-focus event to gh-cm-editor
  • Loading branch information
disordinary authored and kevinansfield committed Mar 30, 2017
1 parent f05f31f commit f5fc35f
Show file tree
Hide file tree
Showing 17 changed files with 397 additions and 105 deletions.
8 changes: 7 additions & 1 deletion app/components/gh-cm-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@ const CmEditorComponent = Component.extend(InvokeActionMixin, {
editor.getDoc().setValue(this.get('_value'));

// events
editor.on('focus', bind(this, 'set', 'isFocused', true));
editor.on('focus', () => {

run(this, function() {
this.set('isFocused', true);
this.invokeAction('focus-in', editor.getDoc().getValue());
});
});
editor.on('blur', bind(this, 'set', 'isFocused', false));
editor.on('change', () => {
run(this, function () {
Expand Down
31 changes: 31 additions & 0 deletions app/components/gh-editor-title.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,37 @@ export default Component.extend({
}
if (event.keyCode === 13) {
// enter
// on enter we want to split the title, create a new paragraph in the mobile doc and insert it into the content.
let {editor} = window;
let title = this.$('.gh-editor-title');
editor.run((postEditor) => {
let {anchorOffset, focusOffset} = window.getSelection();
let text = title.text();
let startText = ''; // the text before the split
let endText = ''; // the text after the split
// if the selection is not collapsed then we have to delete the text that is selected.
if (anchorOffset !== focusOffset) {
// if the start of the selection is after the end then reverse the selection
if (anchorOffset > focusOffset) {
[anchorOffset, focusOffset] = [focusOffset, anchorOffset];
}
startText = text.substring(0, anchorOffset);
endText = text.substring(focusOffset);
} else {
startText = text.substring(0, anchorOffset);
endText = text.substring(anchorOffset);
}

title.html(startText);

let marker = editor.builder.createMarker(endText);
let newSection = editor.builder.createMarkupSection('p', [marker]);
postEditor.insertSectionBefore(editor.post.sections, newSection, editor.post.sections.head);

let range = newSection.toRange();
range.tail.offset = 0; // colapse range
postEditor.setRange(range);
});
return false;
}

Expand Down
169 changes: 112 additions & 57 deletions app/styles/addons/gh-koenig/gh-koenig.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,59 +23,131 @@
letter-spacing: 0.1px;
}

.dropper-bottom {
border-bottom: 66px solid #5ba4e5;
}

.dropper-top {
border-top: 66px solid #5ba4e5;
}

.dropper-left {
border-left: 66px solid #5ba4e5;
}

.dropper-right {
border-right: 66px solid #5ba4e5;
}

.__mobiledoc-editor div {

}

.kg-card {
position: relative;
display: block; /* required for cursor movement around card */
width: 100%;
display: block;
padding: 10px;
outline:none;
}

.kg-card:hover {
.kg-card:hover, .kg-card.selected {
box-shadow: var(--blue) 0 0 0 1px;
border-radius:10px;
}

.kg-card .card-handle {
.kg-card.selected-hard {
box-shadow: var(--blue) 0 0 0 3px;
}
.kg-card .kg-card-toolbar {
position: absolute;
right: 0px;
left: 0px;
top: 0px;
margin-top: -25px;
height: 20px;
margin-top: -56px;
height: 46px;
width:100%;
display: none;
}

.kg-card:hover .card-handle {
.button-group {
color: color(var(--lightgrey) l(-10%));
background: linear-gradient(
color(var(--darkgrey) l(-3%)),
color(var(--darkgrey) l(-8%))
);
border-top-left-radius: 5px;
border-top-right-radius: 5px;
border-radius:5px;

height:46px;
display:flex;
box-shadow: 0 0 0 1px color(var(--darkgrey) l(-10%)), 0 8px 16px rgba(26,39,49,0.16), rgba(255,255,255,0.09) 0 1px 0 0 inset;
}

/* keeps the hover when the cursor is moving from the card to the toolbar */
.button-group:before {
display: block;
content: "";
position: absolute;
bottom:-9px;
width: 100%;
height: 8px;
}

.kg-card .card-handle label {
font-size: 10px;
}

.button-group:after {
display: block;
content: "";
position: absolute;
bottom:-9px;
left: 50%;
margin-left: -10px;

width: 0;
height: 0;
border-left: transparent 10px solid;
border-right: transparent 10px solid;
border-top: color(var(--darkgrey) l(-10%)) 8px solid;
}


.kg-card:hover .kg-card-toolbar, .kg-card.selected .kg-card-toolbar {
display: flex;
align-items: stretch;
justify-content: space-around;
flex-flow: row wrap;
}

.kg-card .kg-card-toolbar label {
flex-grow: 1;
font-size: 1.3rem;
line-height: 46px;
text-align:center;
vertical-align: middle;
font-weight: bold;
padding:0 18px;
}


.kg-card .kg-card-toolbar button {
display: flex;
justify-content: center;
align-items: center;
height: 46px;
min-width: 32px;
font-size: 1.6rem;
line-height: 30px;
padding:0 5px 0 5px;
transition: text-shadow 0.3s ease;
}
.kg-card .kg-card-toolbar button.kg-card-button-text {
font-size: 1.3rem;
line-height: 46px;
width:70px;
text-align:center;
vertical-align: middle;
padding:0;
}
.kg-card .kg-card-toolbar button.kg-card-button-save {
font-size: 1.3rem;
line-height: 30px;
height:30px;
width:60px;
text-align:center;
vertical-align: middle;
margin:8px;

.kg-card .card-handle button {
background-color: var(--lightgrey);
border: 1px solid var(--midgrey);
font-size: 10px;
min-width: 80px;
color: #fff;
text-shadow: 0 -1px 0 rgba(0,0,0,0.1);
fill: #fff;
background: linear-gradient( rgb(61, 161, 214), rgb(34, 136, 191) );
box-shadow: 0 1px 0 rgba(0,0,0,0.12);
border-radius:5px;
}
.kg-card .kg-card-toolbar button.kg-card-delete {
text-transform: none !important;
font-family: "ghosticons" !important;
font-size: 1rem;
line-height: 1;
font-weight: normal !important;
font-style: normal !important;
font-variant: normal !important;
}

.kg-card textarea {
Expand All @@ -86,28 +158,11 @@
resize: none;
}

.card-handle button:hover {
.kg-card-toolbar button:hover {
background-color: #718087;
color: #fff;
}

.card-handle button.confirm {
animation-duration: 1s;
animation-name: rotate;
background-color: red;
color: #e9e8dd;
}

.card-handle button.move {
background-image: url('http: //localhost: 4200/assets/move.png');
background-color: #9fbb58;
margin-left: -10px;
margin-right: 20px;

cursor: -webkit-grab;
cursor: -moz-grab;
}



textarea.ed_code {
Expand Down
2 changes: 1 addition & 1 deletion lib/gh-koenig/addon/cards/card-hr_dom.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default {
name: 'card-hr',
label: 'HR Card',
label: 'Divider',
icon: '',
genus: 'ember',
buttons: {
Expand Down
4 changes: 2 additions & 2 deletions lib/gh-koenig/addon/cards/card-html_dom.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export default {
name: 'card-html',
label: 'HTML Card',
label: 'Embed',
icon: '',
genus: 'ember',
buttons: {
preview: true
edit: true
}
};
2 changes: 1 addition & 1 deletion lib/gh-koenig/addon/cards/card-image_dom.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default {
name: 'card-image',
label: 'Image Card',
label: 'Image',
icon: '',
genus: 'ember'
};
4 changes: 2 additions & 2 deletions lib/gh-koenig/addon/cards/card-markdown_dom.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default {
name: 'card-markdown',
label: 'Markdown Card',
label: 'Markdown',
icon: '',
genus: 'ember',
buttons: {preview: true}
buttons: {edit: true}
};
9 changes: 6 additions & 3 deletions lib/gh-koenig/addon/components/cards/card-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import Component from 'ember-component';
import layout from '../../templates/components/card-html';
import computed from 'ember-computed';
import observer from 'ember-metal/observer';
import {invokeAction} from 'ember-invoke-action';

export default Component.extend({
layout,
isEditing: true,

hasRendered: false,
save: observer('doSave', function () {
this.get('env').save(this.get('payload'), false);
}),
Expand All @@ -28,8 +29,10 @@ export default Component.extend({
this.isEditing = !payload.hasOwnProperty('html');
this.isEditing = true;
},

didRender() {
actions: {
selectCard() {
invokeAction(this, 'selectCard');
}
}
});

Expand Down
16 changes: 12 additions & 4 deletions lib/gh-koenig/addon/components/cards/card-markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ export default Component.extend({
ajax: injectService(),

editing: observer('isEditing', function () {
if (!this.isEditing) {
this.set('preview', formatMarkdown([this.get('payload').markdown]));
}
// if (!this.isEditing) {
// this.set('preview', formatMarkdown([this.get('payload').markdown]));
// }
}),
preview: computed('value', function() {
return formatMarkdown([this.get('payload').markdown]);
}),
save: observer('doSave', function () {
this.get('env').save(this.get('payload'), false);
}),

value: computed('payload', {
Expand All @@ -42,7 +48,6 @@ export default Component.extend({
}

}),

_uploadStarted() {
invokeAction(this, 'uploadStarted');
},
Expand Down Expand Up @@ -231,6 +236,9 @@ export default Component.extend({
saveUrl() {
let url = this.get('url');
invokeAction(this, 'update', url);
},
selectCard() {
invokeAction(this, 'selectCard');
}
}

Expand Down
Loading

0 comments on commit f5fc35f

Please sign in to comment.