Skip to content

Commit

Permalink
Add prompt button, remove execCommand for links
Browse files Browse the repository at this point in the history
fixes #98
  • Loading branch information
bantic committed Sep 1, 2015
1 parent 758f8ff commit dcab0ad
Show file tree
Hide file tree
Showing 23 changed files with 403 additions and 420 deletions.
30 changes: 2 additions & 28 deletions src/js/commands/bold.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,10 @@
import TextFormatCommand from './text-format';
import {
any
} from '../utils/array-utils';

export default class BoldCommand extends TextFormatCommand {
constructor(editor) {
super({
super(editor, {
tag: 'strong',
name: 'bold',
button: '<i class="ck-icon-bold"></i>'
});
this.editor = editor;
const { builder } = this.editor;
this.markup = builder.createMarkup('strong');
}
exec() {
let markerRange = this.editor.cursor.offsets;
if (!markerRange.headSection || !markerRange.tailSection) {
return;
}
let markers = this.editor.run((postEditor) => {
return postEditor.applyMarkupToMarkers(markerRange, this.markup);
});
this.editor.selectMarkers(markers);
}
unexec() {
let markerRange = this.editor.cursor.offsets;
let markers = this.editor.run((postEditor) => {
return postEditor.removeMarkupFromMarkers(markerRange, this.markup);
});
this.editor.selectMarkers(markers);
}
isActive() {
return any(this.editor.activeMarkers, m => m.hasMarkup(this.markup));
}
}
14 changes: 3 additions & 11 deletions src/js/commands/format-block.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import TextFormatCommand from './text-format';
import {
any
} from '../utils/array-utils';
import { any } from '../utils/array-utils';

class FormatBlockCommand extends TextFormatCommand {
constructor(editor, options={}) {
super(options);
this.editor = editor;
super(editor, options);
}

isActive() {
const editor = this.editor;
const activeSections = editor.activeSections;

return any(activeSections, section => {
return any(this.mappedTags, t => section.tagName === t);
});
return any(this.editor.activeSections, s => s.tagName === this.tag);
}

exec() {
Expand Down
29 changes: 2 additions & 27 deletions src/js/commands/italic.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,11 @@
import TextFormatCommand from './text-format';
import {
any
} from '../utils/array-utils';

export default class ItalicCommand extends TextFormatCommand {
constructor(editor) {
super({
super(editor, {
tag: 'em',
name: 'italic',
button: '<i class="ck-icon-italic"></i>'
});
this.editor = editor;
const { builder } = this.editor;
this.markup = builder.createMarkup('em');
}
exec() {
let markerRange = this.editor.cursor.offsets;
if (!markerRange.headSection || !markerRange.tailSection) {
return;
}
let markers = this.editor.run((postEditor) => {
return postEditor.applyMarkupToMarkers(markerRange, this.markup);
});
this.editor.selectMarkers(markers);
}
unexec() {
let markerRange = this.editor.cursor.offsets;
let markers = this.editor.run((postEditor) => {
return postEditor.removeMarkupFromMarkers(markerRange, this.markup);
});
this.editor.selectMarkers(markers);
}
isActive() {
return any(this.editor.activeMarkers, m => m.hasMarkup(this.markup));
}
}
72 changes: 40 additions & 32 deletions src/js/commands/link.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,46 @@
import TextFormatCommand from './text-format';
import Prompt from '../views/prompt';
import { getSelectionTagName } from '../utils/selection-utils';
import { inherit } from 'content-kit-utils';

var RegExpHttp = /^https?:\/\//i;

function LinkCommand() {
TextFormatCommand.call(this, {
name: 'link',
tag: 'a',
action: 'createLink',
removeAction: 'unlink',
button: '<i class="ck-icon-link"></i>',
prompt: new Prompt({
command: this,
placeholder: 'Enter a url, press return...'
})
});
}
inherit(LinkCommand, TextFormatCommand);
import { any } from 'content-kit-editor/utils/array-utils';

export default class LinkCommand extends TextFormatCommand {
constructor(editor) {
super(editor, {
name: 'link',
tag: 'a',
button: '<i class="ck-icon-link"></i>'
});
}

LinkCommand.prototype.exec = function(url) {
if (!url) {
return LinkCommand._super.prototype.unexec.call(this);
isActive() {
return any(this.editor.activeMarkers, m => m.hasMarkup(this.tag));
}

if(this.tag === getSelectionTagName()) {
this.unexec();
} else {
if (!RegExpHttp.test(url)) {
url = 'http://' + url;
}
LinkCommand._super.prototype.exec.call(this, url);
exec(url) {
const range = this.editor.cursor.offsets;

let markers = this.editor.run(postEditor => {
const markup = postEditor.builder.createMarkup('a', ['href', url]);
return postEditor.applyMarkupToMarkers(range, markup);
});

if (markers.length) {
let lastMarker = markers[markers.length - 1];
this.editor.cursor.moveToMarker(lastMarker, lastMarker.length);
} /* else {
// FIXME should handle the case when linking creating no new markers
// this.editor.cursor.moveToSection(range.head.section);
} */
}
};

export default LinkCommand;
unexec() {
const range = this.editor.cursor.offsets;

const markers = this.editor.run(postEditor => {
return postEditor.removeMarkupFromMarkers(
range,
markup => markup.hasTag('a')
);
});

this.editor.selectMarkers(markers);
}
}
3 changes: 1 addition & 2 deletions src/js/commands/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import TextFormatCommand from './text-format';

export default class ListCommand extends TextFormatCommand {
constructor(editor, options) {
super(options);
this.editor = editor;
super(editor, options);
}

isActive() {
Expand Down
38 changes: 26 additions & 12 deletions src/js/commands/text-format.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import Command from './base';
import { any } from '../utils/array-utils';

export default class TextFormatCommand extends Command {
constructor(options={}) {
constructor(editor, options={}) {
super(options);

this.editor = editor;
this.tag = options.tag;
this.mappedTags = options.mappedTags || [];
if (this.tag) {
this.mappedTags.push(this.tag);
}
this.action = options.action || this.name;
this.removeAction = options.removeAction || this.action;
}

exec(value) {
document.execCommand(this.action, false, value || null);
get markup() {
if (this._markup) { return this._markup; }
const { builder } = this.editor;
this._markup = builder.createMarkup(this.tag);
return this._markup;
}

isActive() {
return any(this.editor.activeMarkers, m => m.hasMarkup(this.markup));
}

exec() {
const range = this.editor.cursor.offsets;
const markers = this.editor.run((postEditor) => {
return postEditor.applyMarkupToMarkers(range, this.markup);
});
this.editor.selectMarkers(markers);
}

unexec(value) {
document.execCommand(this.removeAction, false, value || null);
unexec() {
const range = this.editor.cursor.offsets;
const markers = this.editor.run((postEditor) => {
return postEditor.removeMarkupFromMarkers(range, this.markup);
});
this.editor.selectMarkers(markers);
}
}
40 changes: 10 additions & 30 deletions src/js/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import EmbedIntent from '../views/embed-intent';
import PostEditor from './post';

import ReversibleToolbarButton from '../views/reversible-toolbar-button';
import ReversiblePromptButton from '../views/reversible-prompt-button';
import BoldCommand from '../commands/bold';
import ItalicCommand from '../commands/italic';
import LinkCommand from '../commands/link';
Expand Down Expand Up @@ -54,10 +55,6 @@ const defaults = {
// causing the stickyToolbar to accidentally be auto-activated
// in tests
stickyToolbar: false, // !!('ontouchstart' in window),
textFormatCommands: [
new LinkCommand()
],
autoTypingCommands: [],
cards: [],
cardOptions: {},
unknownCardHandler: () => {
Expand Down Expand Up @@ -89,25 +86,6 @@ function bindContentEditableTypingListeners(editor) {
});
}

function bindAutoTypingListeners(editor) {
// Watch typing patterns for auto format commands (e.g. lists '- ', '1. ')
editor.addEventListener(editor.element, 'keyup', function(e) {
var commands = editor.autoTypingCommands;
var count = commands && commands.length;
var selection, i;

if (count) {
selection = window.getSelection();
for (i = 0; i < count; i++) {
if (commands[i].checkAutoFormat(selection.anchorNode)) {
e.stopPropagation();
return;
}
}
}
});
}

function bindSelectionEvent(editor) {
/**
* The following events/sequences can create a selection and are handled:
Expand Down Expand Up @@ -193,12 +171,16 @@ function makeButtons(editor) {
const italicCommand = new ItalicCommand(editor);
const italicButton = new ReversibleToolbarButton(italicCommand, editor);

const linkCommand = new LinkCommand(editor);
const linkButton = new ReversiblePromptButton(linkCommand, editor);

return [
headingButton,
subheadingButton,
quoteButton,
boldButton,
italicButton
italicButton,
linkButton
];
}

Expand Down Expand Up @@ -292,23 +274,21 @@ class Editor {
clearChildNodes(element);

bindContentEditableTypingListeners(this);
bindAutoTypingListeners(this);
bindDragAndDrop(this);
bindSelectionEvent(this);
bindKeyListeners(this);
this.addEventListener(element, 'input', () => this.handleInput());

this._initEmbedCommands();

this.addView(new TextFormatToolbar({
this.toolbar = new TextFormatToolbar({
editor: this,
rootElement: element,
// FIXME -- eventually all the commands should migrate to being buttons
// that can be added
commands: this.textFormatCommands,
commands: [],
buttons: makeButtons(this),
sticky: this.stickyToolbar
}));
});
this.addView(this.toolbar);

this.addView(new Tooltip({
rootElement: element,
Expand Down
4 changes: 2 additions & 2 deletions src/js/editor/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,10 +610,10 @@ class PostEditor {
* @return {Array} of markers that are inside the split
* @public
*/
removeMarkupFromMarkers(markerRange, markup) {
removeMarkupFromMarkers(markerRange, markupOrMarkupCallback) {
const markers = this.splitMarkers(markerRange);
markers.forEach(marker => {
marker.removeMarkup(markup);
marker.removeMarkup(markupOrMarkupCallback);
marker.section.renderNode.markDirty();
});

Expand Down
21 changes: 19 additions & 2 deletions src/js/models/marker.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import {
} from '../utils/dom-utils';
import {
detect,
commonItemLength
commonItemLength,
forEach,
filter
} from 'content-kit-editor/utils/array-utils';
import LinkedItem from "content-kit-editor/utils/linked-item";

Expand Down Expand Up @@ -50,7 +52,22 @@ const Marker = class Marker extends LinkedItem {
this.markups.push(markup);
}

removeMarkup(markup) {
removeMarkup(markupOrMarkupCallback) {
let callback;
if (typeof markupOrMarkupCallback === 'function') {
callback = markupOrMarkupCallback;
} else {
let markup = markupOrMarkupCallback;
callback = (_markup) => _markup === markup;
}

forEach(
filter(this.markups, callback),
m => this._removeMarkup(m)
);
}

_removeMarkup(markup) {
const index = this.markups.indexOf(markup);
if (index !== -1) {
this.markups.splice(index, 1);
Expand Down
5 changes: 5 additions & 0 deletions src/js/models/markup.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class Markup {
}
}

hasTag(tagName) {
tagName = normalizeTagName(tagName);
return this.tagName === tagName;
}

static isValidElement(element) {
let tagName = normalizeTagName(element.tagName);
return VALID_MARKUP_TAGNAMES.indexOf(tagName) !== -1;
Expand Down
Loading

0 comments on commit dcab0ad

Please sign in to comment.