Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

medium-editor

Package Overview
Dependencies
Maintainers
4
Versions
125
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

medium-editor - npm Package Compare versions

Comparing version 4.12.1 to 5.0.0-alpha.0

resources/font-test.html

2

bower.json
{
"name": "medium-editor",
"version": "4.12.1",
"version": "5.0.0-alpha.0",
"homepage": "http://yabwe.github.io/medium-editor/",

@@ -5,0 +5,0 @@ "authors": [

@@ -1,6 +0,1 @@

4.12.1 / 2015-06-02
==================
* Fix break with updateOnEmptySelection option for static toolbars
4.12.0 / 2015-06-01

@@ -7,0 +2,0 @@ ==================

@@ -22,6 +22,2 @@ /*global module, require, process*/

'src/js/events.js',
'src/js/extensions/deprecated/button.js',
'src/js/extensions/deprecated/anchor.js',
'src/js/extensions/deprecated/anchor-preview.js',
'src/js/extensions/deprecated/fontsize.js',
'src/js/extensions/button.js',

@@ -33,6 +29,7 @@ 'src/js/extensions/form.js',

'src/js/extensions/image-dragging.js',
'src/js/extensions/keyboard-commands.js',
'src/js/extensions/fontsize.js',
'src/js/extensions/paste.js',
'src/js/extensions/placeholder.js',
'src/js/toolbar.js',
'src/js/extensions/toolbar.js',
'src/js/defaults/options.js',

@@ -39,0 +36,0 @@ 'src/js/defaults/extensions.js',

{
"name": "medium-editor",
"version": "4.12.1",
"version": "5.0.0-alpha.0",
"author": "Davi Ferreira <hi@daviferreira.com>",

@@ -5,0 +5,0 @@ "contributors": [

@@ -94,29 +94,62 @@ # MediumEditor

### Core options
* __allowMultiParagraphSelection__: enables the toolbar when selecting multiple paragraphs/block elements. Default: true
* __delay__: time in milliseconds to show the toolbar or anchor tag preview. Default: 0
* __disableReturn__: enables/disables the use of the return-key. You can also set specific element behavior by using setting a data-disable-return attribute. Default: false
* __disableDoubleReturn__: allows/disallows two (or more) empty new lines. You can also set specific element behavior by using setting a data-disable-double-return attribute. Default: false
* __disableEditing__: enables/disables adding the contenteditable behavior. Useful for using the toolbar with customized buttons/actions. You can also set specific element behavior by using setting a data-disable-editing attribute. Default: false
* __elementsContainer__: specifies a DOM node to contain MediumEditor's toolbar and anchor preview elements. Default: document.body
* __extensions__: extension to use (see [Custom Buttons and Extensions](https://github.com/yabwe/medium-editor/wiki/Custom-Buttons-and-Extensions)) for more. Default: {}
* __firstHeader__: HTML tag to be used as first header. Default: h3
* __secondHeader__: HTML tag to be used as second header. Default: h4
* __spellcheck__: Enable/disable native contentEditable automatic spellcheck. Default: true
* __standardizeSelectionStart__: Standardizes how the beginning of a range is decided between browsers whenever the selected text is analyzed for updating toolbar buttons status
* __targetBlank__: enables/disables target="\_blank" for anchor tags. Default: false
* __activeButtonClass__: CSS class added to active buttons in the toolbar. Default: `'medium-editor-button-active'`
* __allowMultiParagraphSelection__: enables the toolbar when selecting multiple paragraphs/block elements. Default: `true`
* __buttonLabels__: type of labels on the buttons. Values: 'fontawesome', `{'bold': '<b>b</b>', 'italic': '<i>i</i>'}`. Default: `false`
* __delay__: time in milliseconds to show the toolbar or anchor tag preview. Default: `0`
* __disableReturn__: enables/disables the use of the return-key. You can also set specific element behavior by using setting a data-disable-return attribute. Default: `false`
* __disableDoubleReturn__: allows/disallows two (or more) empty new lines. You can also set specific element behavior by using setting a data-disable-double-return attribute. Default: `false`
* __disableEditing__: enables/disables adding the contenteditable behavior. Useful for using the toolbar with customized buttons/actions. You can also set specific element behavior by using setting a data-disable-editing attribute. Default: `false`
* __elementsContainer__: specifies a DOM node to contain MediumEditor's toolbar and anchor preview elements. Default: `document.body`
* __extensions__: extension to use (see [Custom Buttons and Extensions](https://github.com/yabwe/medium-editor/wiki/Custom-Buttons-and-Extensions)) for more. Default: `{}`
* __firstHeader__: HTML tag to be used as first header. Default: `h3`
* __secondHeader__: HTML tag to be used as second header. Default: `h4`
* __spellcheck__: Enable/disable native contentEditable automatic spellcheck. Default: `true`
* __targetBlank__: enables/disables target="\_blank" for anchor tags. Default: `false`
### Toolbar options
* __activeButtonClass__: CSS class added to active buttons in the toolbar. Default: 'medium-editor-button-active'
The toolbar for MediumEditor is implemented as a built-in extension which automatically displays whenever the user selects some text. The toolbar can hold any set of defined built-in buttons, but can also hold any custom buttons passed in as extensions.
Options for the toolbar are passed as an object taht is a member of the outer options object. Example:
```javascript
var editor = new MediumEditor('.editable', {
toolbar: {
/* These are the default options for the toolbar,
if nothing is passed this is what is used */
buttons: ['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote'],
diffLeft: 0,
diffTop: -10,
firstButtonClass: 'medium-editor-button-first',
lastButtonClass: 'medium-editor-button-last',
standardizeSelectionStart: false,
static: false,
/* options which only apply when static is true */
align: 'center',
sticky: false,
updateOnEmptySelection: false
}
});
```
* __buttons__: the set of buttons to display on the toolbar. Default: `['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote']`
* __buttonLabels__: type of labels on the buttons. Values: 'fontawesome', `{'bold': '<b>b</b>', 'italic': '<i>i</i>'}`. Default: false
* __diffLeft__: value in pixels to be added to the X axis positioning of the toolbar. Default: 0
* __diffTop__: value in pixels to be added to the Y axis positioning of the toolbar. Default: -10
* __disableToolbar__: enables/disables the toolbar, adding only the contenteditable behavior. You can also set specific element behavior by using setting a `data-disable-toolbar` attribute. Default: false
* __firstButtonClass__: CSS class added to the first button in the toolbar. Default: 'medium-editor-button-first'
* __lastButtonClass__: CSS class added to the last button in the toolbar. Default: 'medium-editor-button-last'
* __staticToolbar__: enable/disable the toolbar always displaying in the same location relative to the medium-editor element. Default: false
* __stickyToolbar__: enable/disable the toolbar "sticking" to the medium-editor element when the page is being scrolled. Default: false
* __toolbarAlign__: `left`|`center`|`right` - when using the __staticToolbar__ option, this aligns the static toolbar relative to the medium-editor element. Default: `center`
* __updateOnEmptySelection__: update the state of the toolbar buttons even when the selection is collapse (there is no selection, just a cursor). Default: false
* __diffLeft__: value in pixels to be added to the X axis positioning of the toolbar. Default: `0`
* __diffTop__: value in pixels to be added to the Y axis positioning of the toolbar. Default: `-10`
* __firstButtonClass__: CSS class added to the first button in the toolbar. Default: `'medium-editor-button-first'`
* __lastButtonClass__: CSS class added to the last button in the toolbar. Default: `'medium-editor-button-last'`
* __standardizeSelectionStart__: enables/disables standardizing how the beginning of a range is decided between browsers whenever the selected text is analyzed for updating toolbar buttons status. Default: `false`
* __static__: enable/disable the toolbar always displaying in the same location relative to the medium-editor element. Default: `false`
##### Options which only apply when the `static` option is being used
* __align__: `left`|`center`|`right` - When the __static__ option is `true`, this aligns the static toolbar relative to the medium-editor element. Default: `center`
* __sticky__: When the __static__ option is `true`, this enables/disables the toolbar "sticking" to the viewport and staying visible on the screen while the page scrolls. Default: `false`
* __updateOnEmptySelection__: When the __static__ option is `true`, this enables/disables updating the state of the toolbar buttons even when the selection is collapsed (there is no selection, just a cursor). Default: `false`
To disable the toolbar (which also disables the anchor-preview extension), set the value of the `toolbar` option to `false`:
```javascript
var editor = new MediumEditor('.editable', {
toolbar: false
});
```
### Anchor Preview options

@@ -129,3 +162,2 @@

var editor = new MediumEditor('.editable', {
buttons: ['bold', 'italic', 'underline'],
anchorPreview: {

@@ -141,3 +173,3 @@ /* These are the default options for anchor preview,

* __hideDelay__: time in milliseconds to show the anchor tag preview after the mouse has left the anchor tag. Default: 500
* __hideDelay__: time in milliseconds to show the anchor tag preview after the mouse has left the anchor tag. Default: `500`
* __previewValueSelector__: the default selector to locate where to put the activeAnchor value in the preview. You should only need to override this if you've modified the way in which the anchor-preview extension renders. Default: `'a'`

@@ -152,3 +184,3 @@

##### NOTE:
* If the toolbar is disabled (via __disableToolbar__ or `data-disable-toolbar attribute`) the anchor-preview is automatically disabled.
* If the toolbar is disabled (via `toolbar: false` option or `data-disable-toolbar` attribute) the anchor-preview is automatically disabled.
* If the anchor editing form is not enabled, clicking on the anchor-preview will not allow the href of the link to be edited

@@ -163,3 +195,2 @@

var editor = new MediumEditor('.editable', {
buttons: ['bold', 'italic', 'quote'],
placeholder: {

@@ -173,3 +204,3 @@ /* This example includes the default options for placeholder,

* __text__: Defines the default placeholder for empty contenteditables when __placeholder__ is not set to false. You can overwrite it by setting a `data-placeholder` attribute on the editor elements. Default: 'Type your text'
* __text__: Defines the default placeholder for empty contenteditables when __placeholder__ is not set to false. You can overwrite it by setting a `data-placeholder` attribute on the editor elements. Default: `'Type your text'`

@@ -190,3 +221,5 @@ To disable the placeholder, set the value of the `placeholder` option to `false`:

var editor = new MediumEditor('.editable', {
buttons: ['bold', 'italic', 'underline', 'anchor'],
toolbar: {
buttons: ['bold', 'italic', 'underline', 'anchor']
},
anchor: {

@@ -206,7 +239,7 @@ /* These are the default options for anchor form,

* __customClassOption__: custom class name the user can optionally have added to their created links (ie 'button'). If passed as a non-empty string, a checkbox will be displayed allowing the user to choose whether to have the class added to the created link or not. Default: null
* __customClassOption__: custom class name the user can optionally have added to their created links (ie 'button'). If passed as a non-empty string, a checkbox will be displayed allowing the user to choose whether to have the class added to the created link or not. Default: `null`
* __customClassOptionText__: text to be shown in the checkbox when the __customClassOption__ is being used. Default: `'Button'`
* __linkValidation__: enables/disables check for common URL protocols on anchor links. Default: false
* __linkValidation__: enables/disables check for common URL protocols on anchor links. Default: `false`
* __placeholderText__: text to be shown as placeholder of the anchor input. Default: `'Paste or type a link'`
* __targetCheckbox__: enables/disables displaying a "Open in new window" checkbox, which when checked changes the `target` attribute of the created link. Default: false
* __targetCheckbox__: enables/disables displaying a "Open in new window" checkbox, which when checked changes the `target` attribute of the created link. Default: `false`
* __targetCheckboxText__: text to be shown in the checkbox enabled via the __targetCheckbox__ option. Default: `'Open in new window'`

@@ -221,3 +254,2 @@

var editor = new MediumEditor('.editable', {
buttons: ['bold', 'italic', 'quote'],
paste: {

@@ -235,8 +267,55 @@ /* This example includes the default options for paste,

* __forcePlainText__: Forces pasting as plain text. Default: true
* __cleanPastedHTML__: cleans pasted content from different sources, like google docs etc. Default: false
* __cleanReplacements__: custom pairs (2 element arrays) of RegExp and replacement text to use during paste when __forcePlainText__ or __cleanPastedHTML__ are `true` OR when calling `cleanPaste(text)` helper method. Default: []
* __cleanAttrs__: list of element attributes to remove during paste when __cleanPastedHTML__ is `true` or when calling `cleanPaste(text)` or `pasteHTML(html,options)` helper methods. Default: ['class', 'style', 'dir']
* __cleanTags__: list of element tag names to remove during paste when __cleanPastedHTML__ is `true` or when calling `cleanPaste(text)` or `pasteHTML(html,options)` helper methods. Default: ['meta']
* __forcePlainText__: Forces pasting as plain text. Default: `true`
* __cleanPastedHTML__: cleans pasted content from different sources, like google docs etc. Default: `false`
* __cleanReplacements__: custom pairs (2 element arrays) of RegExp and replacement text to use during paste when __forcePlainText__ or __cleanPastedHTML__ are `true` OR when calling `cleanPaste(text)` helper method. Default: `[]`
* __cleanAttrs__: list of element attributes to remove during paste when __cleanPastedHTML__ is `true` or when calling `cleanPaste(text)` or `pasteHTML(html,options)` helper methods. Default: `['class', 'style', 'dir']`
* __cleanTags__: list of element tag names to remove during paste when __cleanPastedHTML__ is `true` or when calling `cleanPaste(text)` or `pasteHTML(html,options)` helper methods. Default: `['meta']`
### KeyboardCommands Options
The keyboard commands handler is a built-in extension for mapping key-combinations to actions to execute in the editor.
Options for KeyboardCommands are passed as an object that is a member of the outer options object. Example:
```javascript
var editor = new MediumEditor('.editable', {
keyboardCommands: {
/* This example includes the default options for keyboardCommands,
if nothing is passed this is what it used */
commands: [
{
command: 'bold',
key: 'b',
meta: true,
shift: false
},
{
command: 'italic',
key: 'i',
meta: true,
shift: false
},
{
command: 'underline',
key: 'u',
meta: true,
shift: false
}
],
}
});
```
* __commands__: Array of objects describing each command and the combination of keys that will trigger it. Required for each object:
* _command_: argument passed to `editor.execAction()` when key-combination is used
* _key_: keyboard character that triggers this command
* _meta_: whether the ctrl/meta key has to be active or inactive
* _shift_: whether the shift key has to be active or inactive
To disable the keyboard commands, set the value of the `keyboardCommands` option to `false`:
```javascript
var editor = new MediumEditor('.editable', {
keyboardCommands: false
});
```
### Auto Link Options

@@ -246,3 +325,3 @@

To enable built-in auto-link support, set the value of the `autoLink` option to `true':
To enable built-in auto-link support, set the value of the `autoLink` option to `true`:

@@ -270,5 +349,2 @@ ```javascript

var editor = new MediumEditor('.editable', {
buttons: ['bold', 'italic', 'quote'],
diffLeft: 25,
diffTop: 10,
firstHeader: 'h1',

@@ -278,2 +354,7 @@ secondHeader: 'h2',

targetBlank: true,
toolbar: {
buttons: ['bold', 'italic', 'quote'],
diffLeft: 25,
diffTop: 10,
},
anchor: {

@@ -280,0 +361,0 @@ placeholderText: 'Type a link',

@@ -1,4 +0,4 @@

/*global MediumEditor, describe, it, expect, spyOn, AnchorForm,
/*global describe, it, expect, spyOn, AnchorForm,
afterEach, beforeEach, jasmine, fireEvent, setupTestHelpers,
AnchorPreview */
AnchorPreview, MediumEditor */

@@ -15,2 +15,3 @@ describe('Anchor Preview TestCase', function () {

'<a id="test-empty-link" href="">ipsum</a> ' +
'<a id="test-link-disable-preview" data-disable-preview="true" href="http://test.com">ipsum</a> ' +
'<a id="test-markup-link" href="http://test.com"><b>ipsum</b></a> ' +

@@ -27,4 +28,5 @@ '<a id="test-symbol-link" href="http://[{~#custom#~}].com"></a>');

var editor = this.newMediumEditor('.editor', {
delay: 200
}),
delay: 200
}),
toolbar = editor.getExtensionByName('toolbar'),
sel = window.getSelection(),

@@ -53,3 +55,3 @@ anchorPreview = editor.getExtensionByName('anchor-preview'),

// selecting other text should close the toolbar
spyOn(MediumEditor.statics.Toolbar.prototype, 'hideToolbar').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'hideToolbar').and.callThrough();
nextRange = document.createRange();

@@ -61,3 +63,3 @@ nextRange.selectNodeContents(document.getElementById('another-element'));

jasmine.clock().tick(200);
expect(editor.toolbar.hideToolbar).toHaveBeenCalled();
expect(toolbar.hideToolbar).toHaveBeenCalled();
});

@@ -67,5 +69,5 @@

var editor = this.newMediumEditor('.editor', {
delay: 200
}),
anchorPreview = editor.getExtensionByName('anchor-preview');
delay: 200
}),
anchorPreview = editor.getExtensionByName('anchor-preview');

@@ -101,4 +103,4 @@ // show preview

var editor = this.newMediumEditor('.editor', {
delay: 300
}),
delay: 300
}),
anchorPreview = editor.getExtensionByName('anchor-preview');

@@ -124,3 +126,5 @@

var editor = this.newMediumEditor('.editor'),
anchorPreview = editor.getExtensionByName('anchor-preview');
anchorPreview = editor.getExtensionByName('anchor-preview'),
anchor = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');

@@ -135,4 +139,4 @@ // show preview

expect(editor.toolbar.isDisplayed()).toBe(true);
expect(editor.getExtensionByName('anchor').isDisplayed()).toBe(true);
expect(toolbar.isDisplayed()).toBe(true);
expect(anchor.isDisplayed()).toBe(true);
});

@@ -142,4 +146,4 @@

var editor = this.newMediumEditor('.editor', {
delay: 200
}),
delay: 200
}),
anchorPreview = editor.getExtensionByName('anchor-preview');

@@ -156,16 +160,24 @@

it('should not be present when anchorPreview option is set to false', function () {
it('should be displayed when the link has data attribute to disable preview', function () {
var editor = this.newMediumEditor('.editor', {
anchorPreview: false
}),
delay: 200
}),
anchorPreview = editor.getExtensionByName('anchor-preview');
expect(anchorPreview).toBeUndefined();
expect(document.querySelector('.medium-editor-anchor-preview')).toBeNull();
// show preview
spyOn(AnchorPreview.prototype, 'showPreview').and.callThrough();
fireEvent(document.getElementById('test-link-disable-preview'), 'mouseover');
// preview shows only after delay
jasmine.clock().tick(250);
expect(anchorPreview.showPreview).toHaveBeenCalled();
// showPreview is called but the preview isn't displayed
expect(anchorPreview.getPreviewElement().classList.contains('medium-toolbar-arrow-over')).toBe(false);
});
it('should not be present when deprecated disableAnchorPreview option is passed', function () {
it('should NOT be present when anchorPreview option is set to false', function () {
var editor = this.newMediumEditor('.editor', {
disableAnchorPreview: true
}),
anchorPreview: false
}),
anchorPreview = editor.getExtensionByName('anchor-preview');

@@ -177,6 +189,6 @@

it('should not be present when disableToolbar option is passed', function () {
it('should not be present when toolbar option is disabled', function () {
var editor = this.newMediumEditor('.editor', {
disableToolbar: true
}),
toolbar: false
}),
anchorPreview = editor.getExtensionByName('anchor-preview');

@@ -183,0 +195,0 @@

@@ -20,14 +20,17 @@ /*global MediumEditor, describe, it, expect, spyOn,

it('should not hide the toolbar when mouseup fires inside the anchor form', function () {
var editor = this.newMediumEditor('.editor', { buttonLabels: 'fontawesome' }),
anchorExtension = editor.getExtensionByName('anchor');
var editor = this.newMediumEditor('.editor', {
buttonLabels: 'fontawesome'
}),
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
var button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
var button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(button, 'click');
expect(editor.toolbar.isDisplayed()).toBe(true);
expect(toolbar.isDisplayed()).toBe(true);
expect(anchorExtension.isDisplayed()).toBe(true);
fireEvent(anchorExtension.getInput(), 'mouseup');
expect(editor.toolbar.isDisplayed()).toBe(true);
expect(toolbar.isDisplayed()).toBe(true);
expect(anchorExtension.isDisplayed()).toBe(true);

@@ -39,2 +42,3 @@ });

anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar'),
code = 'k'.charCodeAt(0);

@@ -50,3 +54,3 @@

expect(editor.toolbar.isDisplayed()).toBe(true);
expect(toolbar.isDisplayed()).toBe(true);
expect(anchorExtension.isDisplayed()).toBe(true);

@@ -60,6 +64,7 @@ });

var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar'),
button, input;
selectElementContents(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(button, 'click');

@@ -78,2 +83,3 @@ input = editor.getExtensionByName('anchor').getInput();

var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar'),
button,

@@ -83,3 +89,3 @@ input;

selectElementContents(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(button, 'click');

@@ -110,17 +116,2 @@ input = editor.getExtensionByName('anchor').getInput();

});
it('should add http:// if need be and deprecated checkLinkFormat option is set to true', function () {
var editor = this.newMediumEditor('.editor', {
checkLinkFormat: true // deprecated
}),
link,
anchorExtension = editor.getExtensionByName('anchor');
selectElementContentsAndFire(editor.elements[0]);
anchorExtension.showForm('test.com');
fireEvent(anchorExtension.getForm().querySelector('a.medium-editor-toolbar-save'), 'click');
link = editor.elements[0].querySelector('a');
expect(link).not.toBeNull();
expect(link.href).toBe('http://test.com/');
});
it('should not change protocol when a valid one is included', function () {

@@ -167,23 +158,2 @@ var editor = this.newMediumEditor('.editor', {

});
it('should add target="_blank" when "open in a new window" checkbox is enabled via deprecated anchorTarget option and checked', function () {
var editor = this.newMediumEditor('.editor', {
anchorTarget: true // deprecated
}),
anchorExtension = editor.getExtensionByName('anchor'),
targetCheckbox,
link;
selectElementContentsAndFire(editor.elements[0]);
anchorExtension.showForm('http://test.com');
expect(anchorExtension.isDisplayed()).toBe(true);
targetCheckbox = anchorExtension.getForm().querySelector('input.medium-editor-toolbar-anchor-target');
expect().not.toBeNull(targetCheckbox);
targetCheckbox.checked = true;
fireEvent(anchorExtension.getForm().querySelector('a.medium-editor-toolbar-save'), 'click');
expect(anchorExtension.isDisplayed()).toBe(false);
link = editor.elements[0].querySelector('a');
expect(link).not.toBeNull();
expect(link.target).toBe('_blank');
});
it('should add target="_blank" when respective option is set to true', function () {

@@ -207,6 +177,6 @@ var editor = this.newMediumEditor('.editor', {

var editor = this.newMediumEditor('.editor', {
anchor: {
customClassOption: 'btn btn-default'
}
}),
anchor: {
customClassOption: 'btn btn-default'
}
}),
save,

@@ -217,6 +187,7 @@ input,

opts,
anchorExtension = editor.getExtensionByName('anchor');
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContents(editor.elements[0]);
save = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
save = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(save, 'click');

@@ -246,41 +217,2 @@

});
it('should create a button when deprecated anchorButton + anchorButtonClass options are used', function () {
spyOn(MediumEditor.prototype, 'createLink').and.callThrough();
var editor = this.newMediumEditor('.editor', {
anchorButton: true,
anchorButtonClass: 'btn btn-default'
}),
save,
input,
button,
link,
opts,
anchorExtension = editor.getExtensionByName('anchor');
selectElementContents(editor.elements[0]);
save = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(save, 'click');
input = anchorExtension.getInput();
input.value = 'test';
button = anchorExtension.getForm().querySelector('input.medium-editor-toolbar-anchor-button');
button.setAttribute('type', 'checkbox');
button.checked = true;
fireEvent(input, 'keyup', {
keyCode: Util.keyCode.ENTER
});
opts = {
url: 'test',
target: '_self',
buttonClass: 'btn btn-default'
};
expect(editor.createLink).toHaveBeenCalledWith(opts);
link = editor.elements[0].querySelector('a');
expect(link).not.toBeNull();
expect(link.classList.contains('btn')).toBe(true);
expect(link.classList.contains('btn-default')).toBe(true);
});
});

@@ -290,10 +222,11 @@

it('should close the link form when user clicks on cancel', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor'),
button,
cancel,
anchorExtension = editor.getExtensionByName('anchor');
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
cancel = anchorExtension.getForm().querySelector('a.medium-editor-toolbar-close');

@@ -303,3 +236,3 @@ fireEvent(button, 'click');

fireEvent(cancel, 'click');
expect(editor.toolbar.showAndUpdateToolbar).toHaveBeenCalled();
expect(toolbar.showAndUpdateToolbar).toHaveBeenCalled();
expect(anchorExtension.isDisplayed()).toBe(false);

@@ -310,6 +243,7 @@ });

var editor = this.newMediumEditor('.editor'),
anchorExtension = editor.getExtensionByName('anchor');
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
fireEvent(editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]'), 'click');
fireEvent(toolbar.getToolbarElement().querySelector('[data-action="createLink"]'), 'click');
expect(anchorExtension.isDisplayed()).toBe(true);

@@ -328,8 +262,9 @@ fireEvent(anchorExtension.getInput(), 'keyup', {

editor = this.newMediumEditor('.editor'),
anchorExtension = editor.getExtensionByName('anchor');
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(button, 'click');
expect(editor.toolbar.getToolbarActionsElement().style.display).toBe('none');
expect(toolbar.getToolbarActionsElement().style.display).toBe('none');
expect(anchorExtension.isDisplayed()).toBe(true);

@@ -343,6 +278,7 @@ expect(anchorExtension.showForm).toHaveBeenCalled();

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(11); // checkSelection delay
button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(button, 'click');

@@ -349,0 +285,0 @@ expect(this.el.innerHTML).toBe('link');

@@ -20,6 +20,7 @@ /*global MediumEditor, describe, it, expect, spyOn, AnchorForm,

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]');
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]');
fireEvent(button, 'click');

@@ -32,6 +33,7 @@ expect(button.className).toContain('medium-editor-button-active');

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]');
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]');
fireEvent(button, 'click');

@@ -44,6 +46,7 @@ expect(editor.checkSelection).toHaveBeenCalled();

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(11); // checkSelection delay
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]');
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]');
expect(button.className).toContain('medium-editor-button-active');

@@ -57,38 +60,40 @@ fireEvent(button, 'click');

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]');
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]');
fireEvent(button, 'click');
expect(editor.execAction).toHaveBeenCalledWith('bold');
});
});
it('should execute the button action on shortcut', function () {
spyOn(MediumEditor.prototype, 'execAction');
var editor = this.newMediumEditor('.editor'),
code = 'b'.charCodeAt(0);
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
fireEvent(editor.elements[0], 'keydown', {
keyCode: code,
ctrlKey: true,
metaKey: true
});
expect(editor.execAction).toHaveBeenCalled();
describe('Button default config', function () {
it('should be accesible via defaults property of the button prototype', function () {
expect(MediumEditor.extensions.button.prototype.defaults['bold']).toBeTruthy();
expect(MediumEditor.extensions.button.prototype.defaults['anchor']).toBeFalsy();
});
it('should not execute the button action when shift key is pressed', function () {
spyOn(MediumEditor.prototype, 'execAction');
var editor = this.newMediumEditor('.editor'),
code = 'b'.charCodeAt(0);
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
fireEvent(editor.elements[0], 'keydown', {
keyCode: code,
ctrlKey: true,
metaKey: true,
shiftKey: true
it('should be check-able via static Button.isBuiltInButton() method', function () {
expect(MediumEditor.extensions.button.isBuiltInButton('bold')).toBe(true);
expect(MediumEditor.extensions.button.isBuiltInButton('anchor')).toBe(false);
});
});
describe('Button constructor', function () {
it('should accept a set of config options', function () {
var italicConfig = MediumEditor.extensions.button.prototype.defaults['italic'],
italicButton = new MediumEditor.extensions.button(italicConfig);
Object.keys(italicConfig).forEach(function (prop) {
expect(italicButton[prop]).toBe(italicConfig[prop]);
});
expect(editor.execAction).not.toHaveBeenCalled();
});
it('should accept a built-in button name', function () {
var italicButtonOne = new MediumEditor.extensions.button(MediumEditor.extensions.button.prototype.defaults['italic']),
italicButtonTwo = new MediumEditor.extensions.button('italic');
expect(italicButtonOne).toEqual(italicButtonTwo);
});
});

@@ -101,3 +106,3 @@

allButtons = [],
buttonsData = MediumEditor.statics.ButtonsData,
buttonsData = MediumEditor.extensions.button.prototype.defaults,
currButton,

@@ -132,6 +137,9 @@ tempEl;

editor = this.newMediumEditor('.editor', {
buttons: allButtons
});
toolbar: {
buttons: allButtons
}
}),
toolbar = editor.getExtensionByName('toolbar');
Object.keys(customLabels).forEach(function (buttonName) {
button = editor.toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
button = toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
expect(button).not.toBeUndefined();

@@ -146,5 +154,8 @@ expect(button.getAttribute('aria-label')).toBe(customLabels[buttonName]);

editor = this.newMediumEditor('.editor', {
buttons: allButtons
});
expect(editor.toolbar.getToolbarElement().querySelectorAll('button').length).toBe(allButtons.length);
toolbar: {
buttons: allButtons
}
}),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().querySelectorAll('button').length).toBe(allButtons.length);
selectElementContentsAndFire(editor.elements[0]);

@@ -154,3 +165,3 @@ jasmine.clock().tick(1);

Object.keys(defaultLabels).forEach(function (buttonName) {
button = editor.toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
button = toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
expect(button).not.toBeUndefined();

@@ -166,6 +177,9 @@ expect(button.innerHTML).toBe(defaultLabels[buttonName].label);

editor = this.newMediumEditor('.editor', {
buttons: allButtons,
toolbar: {
buttons: allButtons
},
buttonLabels: 'fontawesome'
});
expect(editor.toolbar.getToolbarElement().querySelectorAll('button').length).toBe(allButtons.length);
}),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().querySelectorAll('button').length).toBe(allButtons.length);
selectElementContentsAndFire(editor.elements[0]);

@@ -176,3 +190,3 @@ jasmine.clock().tick(1);

action = defaultLabels[buttonName].action;
button = editor.toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
button = toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
expect(button).not.toBeUndefined();

@@ -190,6 +204,9 @@ fireEvent(button, 'click');

editor = this.newMediumEditor('.editor', {
buttons: allButtons,
toolbar: {
buttons: allButtons
},
buttonLabels: customLabels
});
expect(editor.toolbar.getToolbarElement().querySelectorAll('button').length).toBe(allButtons.length);
}),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().querySelectorAll('button').length).toBe(allButtons.length);
selectElementContentsAndFire(editor.elements[0]);

@@ -200,3 +217,3 @@ jasmine.clock().tick(1);

action = defaultLabels[buttonName].action;
button = editor.toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
button = toolbar.getToolbarElement().querySelector('.medium-editor-action-' + buttonName);
expect(button).not.toBeUndefined();

@@ -214,6 +231,7 @@ fireEvent(button, 'click');

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h3"]');
button = toolbar.getToolbarElement().querySelector('[data-action="append-h3"]');
fireEvent(button, 'click');

@@ -230,6 +248,7 @@ if (isIE()) {

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h3"]');
button = toolbar.getToolbarElement().querySelector('[data-action="append-h3"]');
fireEvent(button, 'click');

@@ -245,6 +264,7 @@ // depending on the styling you have,

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0].firstChild);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h3"]');
button = toolbar.getToolbarElement().querySelector('[data-action="append-h3"]');
fireEvent(button, 'click');

@@ -258,3 +278,4 @@ expect(this.el.innerHTML).toBe('<p><b>lorem ipsum</b></p>');

var editor = this.newMediumEditor('.editor'),
buttons = editor.toolbar.getToolbarElement().querySelectorAll('button');
toolbar = editor.getExtensionByName('toolbar'),
buttons = toolbar.getToolbarElement().querySelectorAll('button');
expect(buttons[0].className).toContain('medium-editor-button-first');

@@ -270,5 +291,8 @@ expect(buttons[1].className).not.toContain('medium-editor-button-first');

var editor = this.newMediumEditor('.editor', {
buttons: ['bold']
toolbar: {
buttons: ['bold']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]');

@@ -289,5 +313,8 @@ this.el.innerHTML = '<b>lorem ipsum</b>';

var editor = this.newMediumEditor('.editor', {
buttons: ['bold']
toolbar: {
buttons: ['bold']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]');

@@ -306,5 +333,8 @@ spyOn(document, 'queryCommandState').and.throwError('DOM ERROR');

var editor = this.newMediumEditor('.editor', {
buttons: ['bold']
toolbar: {
buttons: ['bold']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]');

@@ -327,5 +357,6 @@ this.el.innerHTML = '<p><span id="bold-span" style="font-weight: bold">lorem ipsum</span></p>';

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="italic"]');
button = toolbar.getToolbarElement().querySelector('[data-action="italic"]');
fireEvent(button, 'click');

@@ -339,5 +370,8 @@ expect(document.execCommand).toHaveBeenCalled();

var editor = this.newMediumEditor('.editor', {
buttons: ['italic']
toolbar: {
buttons: ['italic']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="italic"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="italic"]');

@@ -358,5 +392,8 @@ this.el.innerHTML = '<i>lorem ipsum</i>';

var editor = this.newMediumEditor('.editor', {
buttons: ['italic']
toolbar: {
buttons: ['italic']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="italic"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="italic"]');

@@ -375,5 +412,8 @@ spyOn(document, 'queryCommandState').and.throwError('DOM ERROR');

var editor = this.newMediumEditor('.editor', {
buttons: ['italic']
toolbar: {
buttons: ['italic']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="italic"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="italic"]');

@@ -395,5 +435,8 @@ this.el.innerHTML = '<p><span id="italic-span" style="font-style: italic">lorem ipsum</span></p>';

var editor = this.newMediumEditor('.editor', {
buttons: ['underline']
toolbar: {
buttons: ['underline']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="underline"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="underline"]');

@@ -411,5 +454,8 @@ this.el.innerHTML = '<u>lorem ipsum</u>';

var editor = this.newMediumEditor('.editor', {
buttons: ['underline']
toolbar: {
buttons: ['underline']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="underline"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="underline"]');

@@ -428,5 +474,8 @@ spyOn(document, 'queryCommandState').and.throwError('DOM ERROR');

var editor = this.newMediumEditor('.editor', {
buttons: ['underline']
toolbar: {
buttons: ['underline']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="underline"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="underline"]');

@@ -448,5 +497,8 @@ this.el.innerHTML = '<p><span id="underline-span" style="text-decoration: underline">lorem ipsum</span></p>';

var editor = this.newMediumEditor('.editor', {
buttons: ['strikethrough']
toolbar: {
buttons: ['strikethrough']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');

@@ -464,5 +516,8 @@ this.el.innerHTML = '<strike>lorem ipsum</strike>';

var editor = this.newMediumEditor('.editor', {
buttons: ['strikethrough']
toolbar: {
buttons: ['strikethrough']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');

@@ -481,5 +536,8 @@ spyOn(document, 'queryCommandState').and.throwError('DOM ERROR');

var editor = this.newMediumEditor('.editor', {
buttons: ['strikethrough']
toolbar: {
buttons: ['strikethrough']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');

@@ -501,5 +559,8 @@ this.el.innerHTML = '<p><span id="strike-span" style="text-decoration: line-through">lorem ipsum</span></p>';

var editor = this.newMediumEditor('.editor', {
buttons: ['superscript']
toolbar: {
buttons: ['superscript']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="superscript"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="superscript"]');

@@ -519,5 +580,8 @@ this.el.innerHTML = '<sup>lorem ipsum</sub>';

var editor = this.newMediumEditor('.editor', {
buttons: ['subscript']
toolbar: {
buttons: ['subscript']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="subscript"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="subscript"]');

@@ -537,5 +601,8 @@ this.el.innerHTML = '<sub>lorem ipsum</sub>';

var editor = this.newMediumEditor('.editor', {
buttons: ['anchor']
toolbar: {
buttons: ['anchor']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');

@@ -553,5 +620,6 @@ this.el.innerHTML = '<p><span id="span-lorem">lorem</span> <a href="#" id="link">ipsum</a></p>';

var button,
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(button, 'click');

@@ -565,5 +633,8 @@ expect(editor.getExtensionByName('anchor').showForm).toHaveBeenCalled();

var editor = this.newMediumEditor('.editor', {
buttons: ['quote']
toolbar: {
buttons: ['quote']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="append-blockquote"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="append-blockquote"]');

@@ -584,5 +655,8 @@ this.el.innerHTML = '<span id="span-lorem">lorem ipsum</span>';

var editor = this.newMediumEditor('.editor', {
buttons: ['image']
toolbar: {
buttons: ['image']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="image"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="image"]');

@@ -602,5 +676,8 @@ this.el.innerHTML = '<span id="span-image">http://i.imgur.com/twlXfUq.jpg</span>';

var editor = this.newMediumEditor('.editor', {
buttons: ['orderedlist', 'unorderedlist']
toolbar: {
buttons: ['orderedlist', 'unorderedlist']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]');

@@ -611,3 +688,3 @@ this.el.innerHTML = '<ol><li id="li-lorem">lorem ipsum</li></ol>';

// Unordered list should not be active
expect(editor.toolbar.getToolbarElement().querySelector('[data-action="insertunorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);
expect(toolbar.getToolbarElement().querySelector('[data-action="insertunorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);

@@ -617,3 +694,3 @@ fireEvent(button, 'click');

// Unordered list should not be active
expect(editor.toolbar.getToolbarElement().querySelector('[data-action="insertunorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);
expect(toolbar.getToolbarElement().querySelector('[data-action="insertunorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);
});

@@ -625,5 +702,8 @@ });

var editor = this.newMediumEditor('.editor', {
buttons: ['unorderedlist', 'orderedlist']
toolbar: {
buttons: ['unorderedlist', 'orderedlist']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="insertunorderedlist"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="insertunorderedlist"]');

@@ -634,3 +714,3 @@ this.el.innerHTML = '<ul><li id="li-lorem">lorem ipsum</li></ul>';

// Ordered list button should not be active
expect(editor.toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);
expect(toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);

@@ -640,3 +720,3 @@ fireEvent(button, 'click');

// Ordered list button should not be active
expect(editor.toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);
expect(toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]').classList.contains('medium-editor-button-active')).toBe(false);
});

@@ -648,5 +728,8 @@ });

var editor = this.newMediumEditor('.editor', {
buttons: ['pre']
toolbar: {
buttons: ['pre']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="append-pre"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="append-pre"]');

@@ -668,6 +751,9 @@ this.el.innerHTML = '<pre><span id="span-lorem">lorem ipsum</span></pre>';

var editor = this.newMediumEditor('.editor', {
buttons: ['justifyCenter', 'justifyRight']
toolbar: {
buttons: ['justifyCenter', 'justifyRight']
}
}),
rightButton = editor.toolbar.getToolbarElement().querySelector('[data-action="justifyRight"]'),
centerButton = editor.toolbar.getToolbarElement().querySelector('[data-action="justifyCenter"]');
toolbar = editor.getExtensionByName('toolbar'),
rightButton = toolbar.getToolbarElement().querySelector('[data-action="justifyRight"]'),
centerButton = toolbar.getToolbarElement().querySelector('[data-action="justifyCenter"]');

@@ -693,8 +779,11 @@ selectElementContentsAndFire(document.getElementById('justify-para-one'));

var editor = this.newMediumEditor('.editor', {
buttons: ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']
toolbar: {
buttons: ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']
}
}),
leftButton = editor.toolbar.getToolbarElement().querySelector('[data-action="justifyLeft"]'),
rightButton = editor.toolbar.getToolbarElement().querySelector('[data-action="justifyRight"]'),
centerButton = editor.toolbar.getToolbarElement().querySelector('[data-action="justifyCenter"]'),
fullButton = editor.toolbar.getToolbarElement().querySelector('[data-action="justifyFull"]');
toolbar = editor.getExtensionByName('toolbar'),
leftButton = toolbar.getToolbarElement().querySelector('[data-action="justifyLeft"]'),
rightButton = toolbar.getToolbarElement().querySelector('[data-action="justifyRight"]'),
centerButton = toolbar.getToolbarElement().querySelector('[data-action="justifyCenter"]'),
fullButton = toolbar.getToolbarElement().querySelector('[data-action="justifyFull"]');

@@ -770,5 +859,8 @@ // First paragraph should have nothing activated (IE will select align-left)

var editor = this.newMediumEditor('.editor', {
buttons: ['removeFormat']
toolbar: {
buttons: ['removeFormat']
}
}),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="removeFormat"]');
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="removeFormat"]');

@@ -800,6 +892,9 @@ expect(button).toBeTruthy();

var editor = this.newMediumEditor('.editor', {
buttons: ['header1', 'header2']
toolbar: {
buttons: ['header1', 'header2']
}
}),
buttonOne = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h3"]'),
buttonTwo = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h4"]');
toolbar = editor.getExtensionByName('toolbar'),
buttonOne = toolbar.getToolbarElement().querySelector('[data-action="append-h3"]'),
buttonTwo = toolbar.getToolbarElement().querySelector('[data-action="append-h4"]');

@@ -822,8 +917,11 @@ this.el.innerHTML = '<h2>lorem</h2><h3>ipsum</h3><h4>dolor</h4>';

var editor = this.newMediumEditor('.editor', {
buttons: ['header1', 'header2'],
toolbar: {
buttons: ['header1', 'header2']
},
firstHeader: 'h1',
secondHeader: 'h5'
}),
buttonOne = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h1"]'),
buttonTwo = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h5"]');
toolbar = editor.getExtensionByName('toolbar'),
buttonOne = toolbar.getToolbarElement().querySelector('[data-action="append-h1"]'),
buttonTwo = toolbar.getToolbarElement().querySelector('[data-action="append-h5"]');

@@ -849,7 +947,10 @@ expect(buttonOne).toBeTruthy();

var editor = this.newMediumEditor('.editor', {
buttons: ['header1', 'header2'],
toolbar: {
buttons: ['header1', 'header2']
},
firstHeader: 'h1'
}),
buttonOne = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h1"]'),
buttonTwo = editor.toolbar.getToolbarElement().querySelector('[data-action="append-h4"]');
toolbar = editor.getExtensionByName('toolbar'),
buttonOne = toolbar.getToolbarElement().querySelector('[data-action="append-h1"]'),
buttonTwo = toolbar.getToolbarElement().querySelector('[data-action="append-h4"]');

@@ -856,0 +957,0 @@ this.el.innerHTML = '<p>lorem ipsum dolor</p>';

@@ -21,8 +21,11 @@ /*global describe, it, expect, spyOn,

var editor = this.newMediumEditor('.editor', {
buttons: ['orderedlist']
toolbar: {
buttons: ['orderedlist']
}
}),
target = editor.elements[0].querySelector('p'),
toolbar = editor.getExtensionByName('toolbar'),
range, sel;
selectElementContentsAndFire(target);
fireEvent(editor.toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]'), 'click');
fireEvent(toolbar.getToolbarElement().querySelector('[data-action="insertorderedlist"]'), 'click');
expect(this.el.innerHTML).toMatch(/^<ol><li>lorem ipsum(<br>)?<\/li><\/ol><ul><li>dolor<\/li><\/ul>?/);

@@ -29,0 +32,0 @@

@@ -38,6 +38,6 @@ /*global describe, it, expect,

it('should set element data attr medium-element to true', function () {
it('should set element data attr medium-editor-element to true', function () {
var editor = this.newMediumEditor('.editor');
expect(editor.elements.length).toBe(1);
expect(this.el.getAttribute('data-medium-element')).toEqual('true');
expect(this.el.getAttribute('data-medium-editor-element')).toEqual('true');
});

@@ -44,0 +44,0 @@

@@ -314,3 +314,4 @@ /*global describe, it, expect, jasmine,

editor = this.newMediumEditor('.editor'),
button = editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]'),
toolbar = editor.getExtensionByName('toolbar'),
button = toolbar.getToolbarElement().querySelector('[data-action="bold"]'),
handler = function (event, editable) {

@@ -317,0 +318,0 @@ firedTarget = editable;

@@ -18,8 +18,7 @@ /*global MediumEditor, describe, it, expect, spyOn,

describe('Editor', function () {
it('should accept a number of extensions as parameter', function () {
var extensions = {
'extension1': {},
'extension2': {}
},
'extension1': {},
'extension2': {}
},
editor = this.newMediumEditor('.editor', {

@@ -31,57 +30,2 @@ extensions: extensions

it('should call methods on all extensions with callExtensions is used', function () {
var Extension = function () {
},
ext1 = new Extension(),
ext2 = new Extension(),
editor = this.newMediumEditor('.editor', {
extensions: {
'one': ext1,
'two': ext2
}
});
Extension.prototype.aMethod = function () {
// just a stub function
};
spyOn(ext1, 'aMethod');
spyOn(ext2, 'aMethod');
editor.callExtensions('aMethod', 'theParam');
expect(ext1.aMethod).toHaveBeenCalledWith('theParam');
expect(ext2.aMethod).toHaveBeenCalledWith('theParam');
});
it('should call init (and pass the deprecated instance of itself) on extensions if the method exists', function () {
var ExtensionOne = function () {
this.init = function (me) {
this.me = me;
};
},
ExtensionTwo = function () {},
ext1,
ext2,
editor;
ExtensionTwo.prototype.init = function (me) {
this.me = me;
};
ext1 = new ExtensionOne();
ext2 = new ExtensionTwo();
editor = this.newMediumEditor('.editor', {
extensions: {
'one': ext1,
'two': ext2
}
});
expect(ext1.me instanceof MediumEditor).toBeTruthy();
expect(ext2.me instanceof MediumEditor).toBeTruthy();
});
it('should set the base property to an instance of MediumEditor', function () {

@@ -99,16 +43,2 @@ var extOne = new MediumEditor.Extension(),

it('should not set the base property when deprecated parent attribute is set to false', function () {
var TempExtension = MediumEditor.Extension.extend({
parent: false
}),
editor = this.newMediumEditor('.editor', {
extensions: {
'temp': new TempExtension()
}
});
expect(editor instanceof MediumEditor).toBeTruthy();
expect(editor.getExtensionByName('temp').base).toBeUndefined();
});
it('should not override the base or name properties of an extension if overriden', function () {

@@ -188,28 +118,12 @@ var TempExtension = MediumEditor.Extension.extend({

var editor = this.newMediumEditor('.editor', {
extensions: {
'temp-extension': extInstance
}
});
extensions: {
'temp-extension': extInstance
}
});
editor.destroy();
expect(extInstance.destroy).toHaveBeenCalled();
});
it('should call deprecated deactivate on extensions when being destroyed if destroy is not implemented', function () {
var TempExtension = MediumEditor.Extension.extend({
deactivate: function () {}
}),
extInstance = new TempExtension();
spyOn(extInstance, 'deactivate');
var editor = this.newMediumEditor('.editor', {
extensions: {
'temp-extension': extInstance
}
});
editor.destroy();
expect(extInstance.deactivate).toHaveBeenCalled();
});
});
describe('Core Extension', function () {
it('exists', function () {

@@ -221,3 +135,2 @@ expect(MediumEditor.Extension).toBeTruthy();

it('provides an .extend method', function () {
expect(Extension.extend).toBeTruthy();

@@ -227,2 +140,3 @@ var Extended = Extension.extend({

});
expect(Extended.prototype.foo).toBe('bar');

@@ -233,3 +147,2 @@ expect(Extended.extend).toBe(Extension.extend);

it('can be passed as an extension', function () {
var Sub, editor, e1, e2;

@@ -256,6 +169,61 @@

expect(e1.init).toHaveBeenCalledWith(editor);
expect(e1.init).toHaveBeenCalledWith();
expect(e1.base).toBe(editor);
});
it('should not add default extensions', function () {
var editor,
Preview, Placeholder, AutoLink, ImageDragging,
extPreview, extPlaceholder, extAutoLink, extImageDragging;
Preview = Extension.extend({ name: 'anchor-preview' });
Placeholder = Extension.extend({ name: 'placeholder' });
AutoLink = Extension.extend({ name: 'auto-link' });
ImageDragging = Extension.extend({ name: 'image-dragging' });
extPreview = new Preview();
extPlaceholder = new Placeholder();
extAutoLink = new AutoLink();
extImageDragging = new ImageDragging();
editor = this.newMediumEditor('.editor', {
extensions: {
'anchor-preview': extPreview,
'placeholder': extPlaceholder,
'auto-link': extAutoLink,
'image-dragging': extImageDragging
}
});
expect(editor.getExtensionByName('anchor-preview')).toBe(extPreview);
expect(editor.getExtensionByName('placeholder')).toBe(extPlaceholder);
expect(editor.getExtensionByName('auto-link')).toBe(extAutoLink);
expect(editor.getExtensionByName('image-dragging')).toBe(extImageDragging);
});
it('should call constructor function if it exists', function () {
var editor, Sub, SubExtend, e1;
SubExtend = {
name: 'Sub',
constructor: function () {
// dummy constructor
return this;
}
};
spyOn(SubExtend, 'constructor');
Sub = Extension.extend(SubExtend);
e1 = new Sub();
editor = this.newMediumEditor('.editor', {
extensions: {
'sub': e1
}
});
expect(SubExtend.constructor).toHaveBeenCalled();
});
});

@@ -270,3 +238,4 @@

'subscribe': ['editableClick', noop],
'execAction': ['bold']
'execAction': ['bold'],
'trigger': ['someEvent', noop, this.el]
},

@@ -297,2 +266,3 @@ tempExtension = new MediumEditor.Extension(),

});
expect(tempExtension.getEditorId()).toBe(editor.id);

@@ -308,2 +278,3 @@ });

});
expect(tempExtension.getEditorElements()).toBe(editor.elements);

@@ -320,2 +291,3 @@ });

});
expect(tempExtension.getEditorOption('disableReturn')).toBe(true);

@@ -327,12 +299,11 @@ expect(tempExtension.getEditorOption('spellcheck')).toBe(editor.options.spellcheck);

describe('Button integration', function () {
var ExtensionWithElement = {
getButton: function () {
var button = document.createElement('button');
button.className = 'extension-button';
button.innerText = 'XXX';
return button;
getButton: function () {
var button = document.createElement('button');
button.className = 'extension-button';
button.innerText = 'XXX';
return button;
},
checkState: function () {}
},
checkState: function () {}
},
ExtensionWithString = {

@@ -349,8 +320,11 @@ getButton: function () {

var editor = this.newMediumEditor('.editor', {
buttons: ['dummy'],
extensions: {
'dummy': ExtensionWithElement
}
});
expect(editor.toolbar.getToolbarElement().querySelectorAll('.extension-button').length).toBe(1);
toolbar: {
buttons: ['dummy']
},
extensions: {
'dummy': ExtensionWithElement
}
}),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().querySelectorAll('.extension-button').length).toBe(1);
});

@@ -360,3 +334,5 @@

var editor = this.newMediumEditor('.editor', {
buttons: ['dummy'],
toolbar: {
buttons: ['dummy']
},
extensions: {

@@ -376,8 +352,11 @@ 'dummy': ExtensionWithElement

var editor = this.newMediumEditor('.editor', {
buttons: ['dummy'],
extensions: {
'dummy': ExtensionWithString
}
});
expect(editor.toolbar.getToolbarElement().querySelectorAll('.extension-button').length).toBe(1);
toolbar: {
buttons: ['dummy']
},
extensions: {
'dummy': ExtensionWithString
}
}),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().querySelectorAll('.extension-button').length).toBe(1);
});

@@ -387,8 +366,11 @@

var editor = this.newMediumEditor('.editor', {
buttons: ['bold'],
extensions: {
'dummy': ExtensionWithElement
}
});
expect(editor.toolbar.getToolbarElement().querySelectorAll('.extension-button').length).toBe(0);
toolbar: {
buttons: ['bold']
},
extensions: {
'dummy': ExtensionWithElement
}
}),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().querySelectorAll('.extension-button').length).toBe(0);
});

@@ -402,3 +384,5 @@

editor = this.newMediumEditor('.editor', {
buttons: ['bold', 'italic'],
toolbar: {
buttons: ['bold', 'italic']
},
extensions: {

@@ -408,6 +392,7 @@ 'bold': ext

});
var toolbar = editor.getExtensionByName('toolbar');
expect(editor.toolbar.getToolbarElement().querySelectorAll('button').length).toBe(1);
expect(editor.toolbar.getToolbarElement().querySelectorAll('button[data-action="italic"]').length).toBe(1);
expect(editor.toolbar.getToolbarElement().querySelectorAll('button[data-action="bold"]').length).toBe(0);
expect(toolbar.getToolbarElement().querySelectorAll('button').length).toBe(1);
expect(toolbar.getToolbarElement().querySelectorAll('button[data-action="italic"]').length).toBe(1);
expect(toolbar.getToolbarElement().querySelectorAll('button[data-action="bold"]').length).toBe(0);
expect(ext.init).toHaveBeenCalled();

@@ -414,0 +399,0 @@ });

@@ -1,5 +0,6 @@

/*global MediumEditor, describe, it, expect, spyOn,
/*global describe, it, expect, spyOn,
afterEach, beforeEach, selectElementContents,
jasmine, fireEvent, setupTestHelpers,
selectElementContentsAndFire, isIE9, FontSizeForm */
selectElementContentsAndFire, isIE9, FontSizeForm,
MediumEditor */

@@ -20,3 +21,7 @@ describe('Font Size Button TestCase', function () {

this.el = this.createElement('div', 'editor', 'lorem ipsum');
this.mediumOpts = { buttons: ['fontsize'] };
this.mediumOpts = {
toolbar: {
buttons: ['fontsize']
}
};
});

@@ -34,8 +39,9 @@

editor = this.newMediumEditor('.editor', this.mediumOpts),
fontSizeExtension = editor.getExtensionByName('fontsize');
fontSizeExtension = editor.getExtensionByName('fontsize'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
button = toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
fireEvent(button, 'click');
expect(editor.toolbar.getToolbarActionsElement().style.display).toBe('none');
expect(toolbar.getToolbarActionsElement().style.display).toBe('none');
expect(fontSizeExtension.isDisplayed()).toBe(true);

@@ -49,4 +55,10 @@ expect(fontSizeExtension.showForm).toHaveBeenCalled();

spyOn(document, 'execCommand').and.callThrough();
var editor = this.newMediumEditor('.editor', { buttons: ['fontsize'], buttonLabels: 'fontawesome' }),
var editor = this.newMediumEditor('.editor', {
toolbar: {
buttons: ['fontsize']
},
buttonLabels: 'fontawesome'
}),
fontSizeExtension = editor.getExtensionByName('fontsize'),
toolbar = editor.getExtensionByName('toolbar'),
button,

@@ -56,3 +68,3 @@ input;

selectElementContentsAndFire(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
button = toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
fireEvent(button, 'click');

@@ -74,6 +86,7 @@

var editor = this.newMediumEditor('.editor', this.mediumOpts),
fontSizeExtension = editor.getExtensionByName('fontsize');
fontSizeExtension = editor.getExtensionByName('fontsize'),
toolbar = editor.getExtensionByName('toolbar');
this.el.innerHTML = '<font size="7">lorem ipsum dolor</font>';
selectElementContentsAndFire(editor.elements[0].firstChild);
fireEvent(editor.toolbar.getToolbarElement().querySelector('[data-action="fontSize"]'), 'click');
fireEvent(toolbar.getToolbarElement().querySelector('[data-action="fontSize"]'), 'click');
expect(fontSizeExtension.showForm).toHaveBeenCalledWith('7');

@@ -87,2 +100,3 @@ });

fontSizeExtension = editor.getExtensionByName('fontsize'),
toolbar = editor.getExtensionByName('toolbar'),
button,

@@ -92,3 +106,3 @@ input;

selectElementContentsAndFire(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
button = toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
fireEvent(button, 'click');

@@ -116,5 +130,6 @@

it('should close the font size form when user clicks on cancel', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor', this.mediumOpts),
fontSizeExtension = editor.getExtensionByName('fontsize'),
toolbar = editor.getExtensionByName('toolbar'),
button,

@@ -125,3 +140,3 @@ input,

selectElementContentsAndFire(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
button = toolbar.getToolbarElement().querySelector('[data-action="fontSize"]');
cancel = fontSizeExtension.getForm().querySelector('a.medium-editor-toobar-close');

@@ -142,3 +157,3 @@

}
expect(editor.toolbar.showAndUpdateToolbar).toHaveBeenCalled();
expect(toolbar.showAndUpdateToolbar).toHaveBeenCalled();
expect(fontSizeExtension.isDisplayed()).toBe(false);

@@ -152,11 +167,12 @@ });

var editor = this.newMediumEditor('.editor', this.mediumOpts),
fontSizeExtension = editor.getExtensionByName('fontsize');
fontSizeExtension = editor.getExtensionByName('fontsize'),
form = fontSizeExtension.getForm();
expect(document.getElementById('medium-editor-toolbar-form-fontsize-1')).toBeTruthy();
expect(MediumEditor.util.isDescendant(document.body, form)).toBe(true);
editor.destroy();
expect(fontSizeExtension.destroy).toHaveBeenCalled();
expect(document.getElementById('medium-editor-toolbar-form-fontsize-1')).not.toBeTruthy();
expect(MediumEditor.util.isDescendant(document.body, form)).toBe(false);
});
});
});

@@ -38,3 +38,3 @@ /*global MediumEditor, describe, it, expect, spyOn,

expect(editor.events).toBeUndefined();
expect(editor.toolbar).toBeUndefined();
expect(editor.getExtensionByName('toolbar')).toBeUndefined();
expect(editor.getExtensionByName('anchor')).toBeUndefined();

@@ -104,13 +104,7 @@ expect(editor.getExtensionByName('anchor-preview')).toBeUndefined();

delay: 0,
diffLeft: 0,
diffTop: -10,
disableReturn: false,
disableDoubleReturn: false,
disableEditing: false,
disableToolbar: false,
autoLink: false,
toolbarAlign: 'center',
elementsContainer: document.body,
imageDragging: true,
standardizeSelectionStart: false,
contentWindow: window,

@@ -121,3 +115,2 @@ ownerDocument: document,

secondHeader: 'h4',
buttons: ['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote'],
buttonLabels: false,

@@ -127,4 +120,2 @@ targetBlank: false,

activeButtonClass: 'medium-editor-button-active',
firstButtonClass: 'medium-editor-button-first',
lastButtonClass: 'medium-editor-button-last',
spellcheck: true

@@ -139,7 +130,9 @@ },

var options = {
diffLeft: 10,
diffTop: 5,
firstHeader: 'h2',
secondHeader: 'h3',
delay: 300,
toolbar: {
diffLeft: 10,
diffTop: 5
},
anchor: {

@@ -162,3 +155,3 @@ placeholderText: 'test',

spyOn(MediumEditor.prototype, 'setup').and.callThrough();
spyOn(MediumEditor.statics.Toolbar.prototype, 'createToolbar').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'createToolbar').and.callThrough();
spyOn(AnchorForm.prototype, 'createForm').and.callThrough();

@@ -168,7 +161,7 @@ spyOn(AnchorPreview.prototype, 'createPreview').and.callThrough();

anchorExtension = editor.getExtensionByName('anchor'),
anchorPreview = editor.getExtensionByName('anchor-preview');
expect(editor.id).toBe(1);
anchorPreview = editor.getExtensionByName('anchor-preview'),
toolbar = editor.getExtensionByName('toolbar');
expect(editor.setup).toHaveBeenCalled();
expect(editor.toolbar).not.toBeUndefined();
expect(editor.toolbar.createToolbar).toHaveBeenCalled();
expect(toolbar).not.toBeUndefined();
expect(toolbar.createToolbar).toHaveBeenCalled();
expect(anchorExtension).not.toBeUndefined();

@@ -182,11 +175,13 @@ expect(anchorExtension.createForm).toHaveBeenCalled();

var editor1 = this.newMediumEditor('.editor'),
firstId = editor1.id,
editor2 = this.newMediumEditor('.editor'),
editor3 = this.newMediumEditor('.editor');
expect(editor1.id).toBe(1);
expect(editor2.id).toBe(2);
expect(editor3.id).toBe(3);
expect(editor2.id).toBe(firstId + 1);
expect(editor3.id).toBe(firstId + 2);
});
it('should not reset ID when destroy and then re-initialized', function () {
it('should not reset id when destroyed and then re-initialized', function () {
var editor1 = this.newMediumEditor('.editor'),
origId = editor1.id,
editor2;

@@ -200,2 +195,3 @@

expect(editor1.id).not.toEqual(editor2.id);
expect(editor1.id).toBe(origId);
});

@@ -202,0 +198,0 @@

@@ -220,28 +220,2 @@ /*global MediumEditor, describe, it, expect, spyOn,

describe('using cleanPaste', function () {
it('should filter inline rich-text by passing deprecated options', function () {
var i,
editorEl = this.el,
editor = this.newMediumEditor('.editor', {
delay: 200,
forcePlainText: false, // deprecated option
cleanPastedHTML: true // deprecated option
});
for (i = 0; i < inlineTests.length; i += 1) {
// move caret to editor
editorEl.innerHTML = 'Before&nbsp;<span id="editor-inner">&nbsp;</span>&nbsp;after.';
selectElementContents(document.getElementById('editor-inner'));
editor.cleanPaste(inlineTests[i].paste);
jasmine.clock().tick(100);
// Firefox and IE: doing an insertHTML while this <span> is selected results in the html being inserted inside of the span
// Firefox replace the &nbsp; other either side of the <span> with a space
// Webkit: doing an insertHTML while this <span> is selected results in the span being replaced completely
expect(editorEl.innerHTML).toMatch(new RegExp('^Before(&nbsp;|\\s)(<span id="editor-inner">)?' + inlineTests[i].output + '(</span>)?(&nbsp;|\\s)after\\.$'));
}
});
it('should filter inline rich-text', function () {

@@ -248,0 +222,0 @@ var i,

@@ -153,10 +153,2 @@ /*global describe, it, expect, Util,

it('should use custom placeholder text when passed as a deprecated option', function () {
var placeholderText = 'Custom placeholder',
editor = this.newMediumEditor('.editor', {
placeholder: placeholderText
});
validatePlaceholderContent(editor.elements[0], placeholderText);
});
it('should use custom placeholder text when passed as the placeholder.text option', function () {

@@ -172,9 +164,2 @@ var placeholderText = 'Custom placeholder',

it('should not set placeholder for empty elements when deprecated disablePlaceholders is set to true', function () {
var editor = this.newMediumEditor('.editor', {
disablePlaceholders: true
});
expect(editor.elements[0].className).not.toContain('medium-editor-placeholder');
});
it('should not set placeholder for empty elements when placeholder is set to false', function () {

@@ -181,0 +166,0 @@ var editor = this.newMediumEditor('.editor', {

/*global MediumEditor, describe, it, expect, spyOn,
afterEach, beforeEach, fireEvent,
jasmine, selectElementContents, setupTestHelpers,
selectElementContentsAndFire, Selection, placeCursorInsideElement */
selectElementContentsAndFire, Selection,
placeCursorInsideElement */

@@ -29,3 +30,5 @@ describe('Selection TestCase', function () {

var editor = this.newMediumEditor('.editor', {
buttons: ['italic', 'underline', 'strikethrough']
toolbar: {
buttons: ['italic', 'underline', 'strikethrough']
}
});

@@ -47,3 +50,5 @@

var editor = this.newMediumEditor('.editor', {
buttons: ['italic', 'underline', 'strikethrough']
toolbar: {
buttons: ['italic', 'underline', 'strikethrough']
}
}),

@@ -71,3 +76,5 @@ link = editor.elements[0].getElementsByTagName('a')[0];

var editor = this.newMediumEditor('.editor', {
buttons: ['italic', 'underline', 'strikethrough']
toolbar: {
buttons: ['italic', 'underline', 'strikethrough']
}
});

@@ -87,4 +94,7 @@

var editor = this.newMediumEditor('.editor', {
buttons: ['italic', 'underline', 'strikethrough']
}),
toolbar: {
buttons: ['italic', 'underline', 'strikethrough']
}
}),
toolbar = editor.getExtensionByName('toolbar'),
button,

@@ -99,3 +109,3 @@ regex;

selectElementContents(editor.elements[0]);
button = editor.toolbar.getToolbarElement().querySelector('[data-action="underline"]');
button = toolbar.getToolbarElement().querySelector('[data-action="underline"]');
fireEvent(button, 'click');

@@ -106,3 +116,3 @@

editor.restoreSelection();
button = editor.toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');
button = toolbar.getToolbarElement().querySelector('[data-action="strikethrough"]');
fireEvent(button, 'click');

@@ -115,28 +125,31 @@ expect(regex.test(editor.elements[0].innerHTML)).toBe(true);

it('should check for selection on mouseup event', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'checkState');
var editor = this.newMediumEditor('.editor');
spyOn(MediumEditor.extensions.toolbar.prototype, 'checkState');
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
fireEvent(editor.elements[0], 'mouseup');
expect(editor.toolbar.checkState).toHaveBeenCalled();
expect(toolbar.checkState).toHaveBeenCalled();
});
it('should check for selection on keyup', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'checkState');
var editor = this.newMediumEditor('.editor');
spyOn(MediumEditor.extensions.toolbar.prototype, 'checkState');
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
fireEvent(editor.elements[0], 'keyup');
expect(editor.toolbar.checkState).toHaveBeenCalled();
expect(toolbar.checkState).toHaveBeenCalled();
});
it('should hide the toolbar if selection is empty', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'setToolbarPosition').and.callThrough();
spyOn(MediumEditor.statics.Toolbar.prototype, 'setToolbarButtonStates').and.callThrough();
spyOn(MediumEditor.statics.Toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor');
editor.toolbar.getToolbarElement().style.display = 'block';
editor.toolbar.getToolbarElement().classList.add('medium-editor-toolbar-active');
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
spyOn(MediumEditor.extensions.toolbar.prototype, 'setToolbarPosition').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'setToolbarButtonStates').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
toolbar.getToolbarElement().style.display = 'block';
toolbar.getToolbarElement().classList.add('medium-editor-toolbar-active');
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
editor.checkSelection();
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(editor.toolbar.setToolbarPosition).not.toHaveBeenCalled();
expect(editor.toolbar.setToolbarButtonStates).not.toHaveBeenCalled();
expect(editor.toolbar.showAndUpdateToolbar).not.toHaveBeenCalled();
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(toolbar.setToolbarPosition).not.toHaveBeenCalled();
expect(toolbar.setToolbarButtonStates).not.toHaveBeenCalled();
expect(toolbar.showAndUpdateToolbar).not.toHaveBeenCalled();
});

@@ -147,36 +160,41 @@

var editor = this.newMediumEditor('.editor', {
allowMultiParagraphSelection: false
});
allowMultiParagraphSelection: false
}),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(document.getElementById('p-one'), { eventToFire: 'focus' });
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
selectElementContentsAndFire(this.el, { eventToFire: 'mouseup' });
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
});
it('should show the toolbar when something is selected', function () {
var editor = this.newMediumEditor('.editor');
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
selectElementContentsAndFire(this.el);
jasmine.clock().tick(501);
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
});
it('should update toolbar position and button states when something is selected', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'setToolbarPosition').and.callThrough();
spyOn(MediumEditor.statics.Toolbar.prototype, 'setToolbarButtonStates').and.callThrough();
spyOn(MediumEditor.statics.Toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor');
spyOn(MediumEditor.extensions.toolbar.prototype, 'setToolbarPosition').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'setToolbarButtonStates').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'showAndUpdateToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(this.el);
jasmine.clock().tick(51);
expect(editor.toolbar.setToolbarPosition).toHaveBeenCalled();
expect(editor.toolbar.setToolbarButtonStates).toHaveBeenCalled();
expect(editor.toolbar.showAndUpdateToolbar).toHaveBeenCalled();
expect(toolbar.setToolbarPosition).toHaveBeenCalled();
expect(toolbar.setToolbarButtonStates).toHaveBeenCalled();
expect(toolbar.showAndUpdateToolbar).toHaveBeenCalled();
});
it('should update button states for static toolbar when updateOnEmptySelection is true and the selection is empty', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'setToolbarButtonStates').and.callThrough();
spyOn(MediumEditor.extensions.toolbar.prototype, 'setToolbarButtonStates').and.callThrough();
var editor = this.newMediumEditor('.editor', {
updateOnEmptySelection: true,
staticToolbar: true
toolbar: {
updateOnEmptySelection: true,
static: true
}
});

@@ -187,3 +205,3 @@

expect(editor.toolbar.setToolbarButtonStates).toHaveBeenCalled();
expect(editor.getExtensionByName('toolbar').setToolbarButtonStates).toHaveBeenCalled();
});

@@ -190,0 +208,0 @@ });

@@ -27,19 +27,2 @@ /*global MediumEditor, describe, it, expect, spyOn, jasmine,

describe('activate() and deactivate()', function () {
it('should be aliases for setup() and destory() for backwards compatability', function () {
var editor = this.newMediumEditor('.editor');
expect(editor.isActive).toBe(true);
spyOn(MediumEditor.prototype, 'destroy').and.callThrough();
editor.deactivate();
expect(editor.isActive).toBe(false);
expect(editor.destroy).toHaveBeenCalled();
spyOn(MediumEditor.prototype, 'setup').and.callThrough();
editor.activate();
expect(editor.isActive).toBe(true);
expect(editor.setup).toHaveBeenCalled();
});
});
describe('Setup', function () {

@@ -86,3 +69,3 @@ it('should init the toolbar and editor elements', function () {

// Store toolbar, since destroy will remove the reference from the editor
toolbar = editor.toolbar;
toolbar = editor.getExtensionByName('toolbar');

@@ -121,12 +104,13 @@ // fire event (handler executed immediately)

editor = this.newMediumEditor('.editor');
var toolbar = editor.getExtensionByName('toolbar');
spyOn(editor.toolbar, 'hideToolbar').and.callThrough(); // via: handleBlur
spyOn(toolbar, 'hideToolbar').and.callThrough(); // via: handleBlur
selectElementContentsAndFire(editor.elements[0], { eventToFire: 'click' });
jasmine.clock().tick(51);
expect(editor.toolbar.hideToolbar).not.toHaveBeenCalled();
expect(toolbar.hideToolbar).not.toHaveBeenCalled();
selectElementContentsAndFire(editor.elements[1], { eventToFire: 'click' });
jasmine.clock().tick(51);
expect(editor.toolbar.hideToolbar).not.toHaveBeenCalled();
expect(toolbar.hideToolbar).not.toHaveBeenCalled();

@@ -136,3 +120,3 @@ selectElementContents(editor.elements[2]);

jasmine.clock().tick(51);
expect(editor.toolbar.hideToolbar).not.toHaveBeenCalled();
expect(toolbar.hideToolbar).not.toHaveBeenCalled();

@@ -139,0 +123,0 @@ elements.forEach(function (element) {

@@ -20,6 +20,7 @@ /*global MediumEditor, describe, it, expect, spyOn,

it('should call the createToolbar method', function () {
spyOn(MediumEditor.statics.Toolbar.prototype, 'createToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor');
expect(editor.toolbar).not.toBeUndefined();
expect(editor.toolbar.createToolbar).toHaveBeenCalled();
spyOn(MediumEditor.extensions.toolbar.prototype, 'createToolbar').and.callThrough();
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar).not.toBeUndefined();
expect(toolbar.createToolbar).toHaveBeenCalled();
});

@@ -30,3 +31,3 @@

var editor = this.newMediumEditor('.editor'),
toolbar = editor.toolbar.getToolbarElement();
toolbar = editor.getExtensionByName('toolbar').getToolbarElement();
expect(toolbar.className).toMatch(/medium-editor-toolbar/);

@@ -39,5 +40,8 @@ expect(document.querySelectorAll('.medium-editor-toolbar').length).toBe(1);

var editor = this.newMediumEditor('.editor', {
buttons: ['bold', 'italic', 'underline']
});
expect(editor.toolbar.getToolbarElement().querySelectorAll('.medium-editor-toolbar-form-anchor').length).toBe(0);
toolbar: {
buttons: ['bold', 'italic', 'underline']
}
}),
toolbar = editor.getExtensionByName('toolbar');
expect(toolbar.getToolbarElement().querySelectorAll('.medium-editor-toolbar-form-anchor').length).toBe(0);
expect(editor.getExtensionByName('anchor')).toBeUndefined();

@@ -55,14 +59,14 @@ });

editor = this.newMediumEditor(document.getElementById('editor-for-toolbar-test'), { delay: 0 });
var toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(document.getElementById('bold_dolorOne'));
jasmine.clock().tick(51);
expect(editor.toolbar.getToolbarElement().querySelector('button[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
expect(toolbar.getToolbarElement().querySelector('button[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
});
it('should not activate buttons in toolbar when stopSelectionUpdates has been called, but should activate buttons after startSelectionUpdates is called', function () {
var editor = null;
this.el.innerHTML = 'lorem ipsum <b><div id="bold_dolorTwo">dolor</div></b>';
editor = this.newMediumEditor(document.querySelectorAll('.editor'), { delay: 0 });
var editor = this.newMediumEditor(document.querySelectorAll('.editor'), { delay: 0 }),
toolbar = editor.getExtensionByName('toolbar');

@@ -73,3 +77,3 @@ editor.stopSelectionUpdates();

jasmine.clock().tick(51);
expect(editor.toolbar.getToolbarElement().querySelector('button[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(false);
expect(toolbar.getToolbarElement().querySelector('button[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(false);

@@ -80,3 +84,3 @@ editor.startSelectionUpdates();

jasmine.clock().tick(51);
expect(editor.toolbar.getToolbarElement().querySelector('button[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
expect(toolbar.getToolbarElement().querySelector('button[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
});

@@ -112,9 +116,10 @@

var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar'),
temp = {
update: function () {
expect(editor.toolbar.positionToolbar).not.toHaveBeenCalled();
expect(toolbar.positionToolbar).not.toHaveBeenCalled();
}
};
spyOn(editor.toolbar, 'positionToolbar').and.callThrough();
spyOn(toolbar, 'positionToolbar').and.callThrough();
spyOn(temp, 'update').and.callThrough();

@@ -126,3 +131,3 @@ this.el.innerHTML = 'position sanity check';

expect(temp.update).toHaveBeenCalled();
expect(editor.toolbar.positionToolbar).toHaveBeenCalled();
expect(toolbar.positionToolbar).toHaveBeenCalled();
});

@@ -175,37 +180,6 @@

it('should call deprecated onShowToolbar option when toolbar is shown and deprecated onHideToolbar option when toolbar is hidden', function () {
var editor,
temp = {
onShow: function () {},
onHide: function () {}
};
spyOn(temp, 'onShow').and.callThrough();
spyOn(temp, 'onHide').and.callThrough();
this.el.innerHTML = 'specOnShowToolbarTest';
editor = this.newMediumEditor('.editor', {
onShowToolbar: temp.onShow,
onHideToolbar: temp.onHide
});
selectElementContentsAndFire(this.el, { eventToFire: 'focus' });
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(temp.onShow).toHaveBeenCalled();
expect(temp.onHide).not.toHaveBeenCalled();
// Remove selection and call check selection, which should make the toolbar be hidden
jasmine.clock().tick(1);
window.getSelection().removeAllRanges();
editor.checkSelection();
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(temp.onHide).toHaveBeenCalled();
});
it('should not hide when selecting text within editor, but release mouse outside of editor', function () {
this.el.innerHTML = 'lorem ipsum';
var editor = this.newMediumEditor('.editor');
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');

@@ -218,3 +192,3 @@ selectElementContentsAndFire(editor.elements[0].firstChild);

expect(editor.toolbar.isDisplayed()).toBe(true);
expect(toolbar.isDisplayed()).toBe(true);
});

@@ -225,3 +199,4 @@

var outsideElement = this.createElement('div', '', 'Click Me, I don\'t clear selection'),
editor = this.newMediumEditor('.editor');
editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');

@@ -232,3 +207,3 @@ outsideElement.setAttribute('style', '-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;');

jasmine.clock().tick(51);
expect(editor.toolbar.isDisplayed()).toBe(true);
expect(toolbar.isDisplayed()).toBe(true);

@@ -241,3 +216,3 @@ fireEvent(outsideElement, 'mousedown');

expect(document.getSelection().rangeCount).toBe(1);
expect(editor.toolbar.isDisplayed()).toBe(false);
expect(toolbar.isDisplayed()).toBe(false);
});

@@ -250,6 +225,9 @@ });

var editor = this.newMediumEditor('.editor', {
staticToolbar: true,
standardizeSelectionStart: true,
updateOnEmptySelection: true
});
toolbar: {
static: true,
updateOnEmptySelection: true,
standardizeSelectionStart: true
}
}),
toolbar = editor.getExtensionByName('toolbar');

@@ -263,3 +241,3 @@ placeCursorInsideElement(this.el.firstChild, 'This is my text'.length);

jasmine.clock().tick(1);
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(this.el.getAttribute('medium-editor-focused')).not.toBeTruthy();

@@ -271,5 +249,8 @@ });

var editor = this.newMediumEditor('.editor', {
staticToolbar: true,
stickyToolbar: true
});
toolbar: {
static: true,
sticky: true
}
}),
toolbar = editor.getExtensionByName('toolbar');

@@ -280,13 +261,16 @@ selectElementContentsAndFire(this.el.querySelector('b'));

jasmine.clock().tick(1); // checkSelection delay
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(toolbar.getToolbarElement().querySelector('[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
});
it('should show and update toolbar buttons when staticToolbar and updateOnEmptySelection options are set to true', function () {
it('should show and update toolbar buttons when toolbar is static and updateOnEmptySelection option is set to true', function () {
this.el.innerHTML = '<b>lorem ipsum</b>';
var editor = this.newMediumEditor('.editor', {
staticToolbar: true,
stickyToolbar: true,
updateOnEmptySelection: true
});
toolbar: {
static: true,
sticky: true,
updateOnEmptySelection: true
}
}),
toolbar = editor.getExtensionByName('toolbar');

@@ -297,4 +281,4 @@ selectElementContentsAndFire(this.el.querySelector('b'));

jasmine.clock().tick(1); // checkSelection delay
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(editor.toolbar.getToolbarElement().querySelector('[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(toolbar.getToolbarElement().querySelector('[data-action="bold"]').classList.contains('medium-editor-button-active')).toBe(true);
});

@@ -310,4 +294,14 @@

editorOne = this.newMediumEditor('.editor', { staticToolbar: true });
editorTwo = this.newMediumEditor(document.getElementById('editor-div-two'), { staticToolbar: true });
editorOne = this.newMediumEditor('.editor', {
toolbar: {
static: true
}
});
editorTwo = this.newMediumEditor(document.getElementById('editor-div-two'), {
toolbar: {
static: true
}
});
var toolbarOne = editorOne.getExtensionByName('toolbar'),
toolbarTwo = editorTwo.getExtensionByName('toolbar');

@@ -322,4 +316,4 @@ selectElementContents(document.getElementById('editor-span-1'));

expect(editorOne.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(editorTwo.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(toolbarOne.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(toolbarTwo.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);

@@ -334,4 +328,4 @@ selectElementContents(document.getElementById('editor-span-2'));

expect(editorOne.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(editorTwo.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(toolbarOne.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(toolbarTwo.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
});

@@ -352,7 +346,7 @@ });

describe('Disable', function () {
it('should not show the toolbar on elements when option disableToolbar is set to true', function () {
it('should not show the toolbar on elements when toolbar option is set to false', function () {
var editor = this.newMediumEditor('.editor', {
disableToolbar: true
toolbar: false
});
expect(editor.options.disableToolbar).toBe(true);
expect(editor.options.toolbar).toBe(false);
expect(document.getElementsByClassName('medium-editor-toolbar-actions').length).toBe(0);

@@ -365,3 +359,3 @@ });

expect(document.getElementsByClassName('medium-editor-toolbar-actions').length).toBe(0);
expect(editor.toolbar).toBeUndefined();
expect(editor.getExtensionByName('toolbar')).toBeUndefined();
});

@@ -376,9 +370,10 @@

editor = this.newMediumEditor(document.querySelectorAll('.editor'));
var toolbar = editor.getExtensionByName('toolbar');
expect(editor.elements.length).toBe(2);
expect(editor.toolbar.getToolbarElement().style.display).toBe('');
expect(toolbar.getToolbarElement().style.display).toBe('');
selectElementContentsAndFire(element);
jasmine.clock().tick(51);
expect(editor.toolbar.getToolbarElement().style.display).toBe('');
expect(toolbar.getToolbarElement().style.display).toBe('');
});

@@ -390,3 +385,4 @@

var editor = this.newMediumEditor(document.querySelectorAll('.editor'), { delay: 0 });
var editor = this.newMediumEditor(document.querySelectorAll('.editor'), { delay: 0 }),
toolbar = editor.getExtensionByName('toolbar');

@@ -396,3 +392,3 @@ selectElementContentsAndFire(document.getElementById('cef_el'));

jasmine.clock().tick(51);
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(false);
});

@@ -407,10 +403,11 @@

editor = this.newMediumEditor(document.querySelectorAll('.editor'));
var toolbar = editor.getExtensionByName('toolbar');
expect(editor.elements.length).toBe(2);
expect(editor.toolbar.getToolbarElement().style.display).toBe('');
expect(toolbar.getToolbarElement().style.display).toBe('');
selectElementContentsAndFire(this.el, { eventToFire: 'focus' });
expect(editor.toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
expect(toolbar.getToolbarElement().classList.contains('medium-editor-toolbar-active')).toBe(true);
});
it('should not try to toggle toolbar when option disabletoolbar is set to true', function () {
it('should not try to toggle toolbar when toolbar option is set to false', function () {
this.createElement('div', 'editor');

@@ -420,6 +417,7 @@ this.el.innerHTML = 'lorem ipsum';

var editor = this.newMediumEditor(document.querySelectorAll('.editor'), {
disableToolbar: true
});
toolbar: false
}),
toolbar = editor.getExtensionByName('toolbar');
expect(editor.toolbar).toBeUndefined();
expect(toolbar).toBeUndefined();

@@ -434,11 +432,60 @@ selectElementContents(this.el);

var editor = this.newMediumEditor('.editor', {
staticToolbar: true,
stickyToolbar: true
});
toolbar: {
static: true,
sticky: true
}
}),
toolbar = editor.getExtensionByName('toolbar');
spyOn(Toolbar.prototype, 'positionToolbarIfShown');
fireEvent(window, 'scroll');
expect(editor.toolbar.positionToolbarIfShown).toHaveBeenCalled();
expect(toolbar.positionToolbarIfShown).toHaveBeenCalled();
});
});
describe('Resizing', function () {
beforeEach(function () {
this.el.innerHTML = 'test content';
});
it('should reset toolbar position', function () {
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
expect(toolbar.getToolbarElement().className.indexOf('active')).toBeGreaterThan(-1);
spyOn(toolbar, 'setToolbarPosition');
fireEvent(window, 'resize');
jasmine.clock().tick(1);
expect(toolbar.setToolbarPosition).toHaveBeenCalled();
});
it('should not call setToolbarPosition when toolbar is not visible', function () {
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar');
spyOn(toolbar, 'setToolbarPosition').and.callThrough();
fireEvent(window, 'resize');
jasmine.clock().tick(1);
expect(toolbar.getToolbarElement().className.indexOf('active')).toBe(-1);
expect(toolbar.setToolbarPosition).not.toHaveBeenCalled();
});
it('should throttle multiple calls to position toolbar', function () {
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar'),
tickTime = 60,
totalTicks;
selectElementContentsAndFire(editor.elements[0]);
jasmine.clock().tick(1);
expect(toolbar.getToolbarElement().className.indexOf('active')).toBeGreaterThan(-1);
spyOn(toolbar, 'setToolbarPosition').and.callThrough();
for (totalTicks = 0; totalTicks < tickTime; totalTicks += 10) {
fireEvent(window, 'resize');
jasmine.clock().tick(10);
}
expect(toolbar.setToolbarPosition.calls.count()).toBeLessThan(3);
});
});
describe('Static & sticky toolbar position', function () {

@@ -448,7 +495,9 @@ it('should position static + sticky toolbar on the left', function () {

var editor = this.newMediumEditor('.editor', {
staticToolbar: true,
stickyToolbar: true,
toolbarAlign: 'left'
}),
toolbar = editor.toolbar.getToolbarElement();
toolbar: {
static: true,
sticky: true,
align: 'left'
}
}),
toolbar = editor.getExtensionByName('toolbar').getToolbarElement();

@@ -466,7 +515,9 @@ selectElementContentsAndFire(this.el.querySelector('b'));

var editor = this.newMediumEditor('.editor', {
staticToolbar: true,
stickyToolbar: true,
toolbarAlign: 'right'
}),
toolbar = editor.toolbar.getToolbarElement();
toolbar: {
static: true,
sticky: true,
align: 'right'
}
}),
toolbar = editor.getExtensionByName('toolbar').getToolbarElement();

@@ -484,7 +535,9 @@ selectElementContentsAndFire(this.el.querySelector('b'));

var editor = this.newMediumEditor('.editor', {
staticToolbar: true,
stickyToolbar: true,
toolbarAlign: 'center'
}),
toolbar = editor.toolbar.getToolbarElement();
toolbar: {
static: true,
sticky: true,
align: 'center'
}
}),
toolbar = editor.getExtensionByName('toolbar').getToolbarElement();

@@ -491,0 +544,0 @@ selectElementContentsAndFire(this.el.querySelector('b'));

@@ -82,38 +82,2 @@ /*global MediumEditor, Util, describe, it, expect, spyOn,

describe('getobject', function () {
it('should get nested objects', function () {
var obj = { a: { b: { c: { d: 10 } } } };
expect(Util.getObject('a.b.c.d', false, obj)).toBe(10);
expect(Util.getObject('a.b.c.d', false, false)).toBe(undefined);
expect(Util.getObject(false, false, obj)).toBe(obj);
expect(Util.getObject('a.b.c', false, obj)).toEqual({ d: 10 });
expect(Util.getObject('a', false, obj)).toEqual({ b: { c: { d: 10 } } });
});
it('should create a path if told to', function () {
var obj = {};
expect(Util.getObject('a.b.c.d', true, obj)).toEqual({});
expect(obj.a.b.c.d).toBeTruthy();
});
it('should NOT create a path', function () {
var obj = {};
expect(Util.getObject('a.b.c.d.e.f.g', false, obj)).toBe(undefined);
expect(obj.a).toBe(undefined);
});
});
describe('setobject', function () {
it('sets returns the value', function () {
var obj = {};
expect(Util.setObject('a.b.c', 10, obj)).toBe(10);
expect(obj.a.b.c).toBe(10);
});
it('sets returns undefined because of empty string', function () {
var obj = {};
expect(Util.setObject('', 10, obj)).toBe(undefined);
});
});
describe('settargetblank', function () {

@@ -302,4 +266,4 @@ it('sets target blank on a A element from a A element', function () {

it('should not get closed tag with data-medium-element', function () {
var el = this.createElement('div', '', '<p>youpi<span data-medium-element="true">my <b>text</b></span></p>'),
it('should not get closed tag with data-medium-editor-element', function () {
var el = this.createElement('div', '', '<p>youpi<span data-medium-editor-element="true">my <b>text</b></span></p>'),
tag = el.querySelector('b').firstChild,

@@ -306,0 +270,0 @@ closestTag = Util.getClosestTag(tag, 'p');

@@ -9,3 +9,3 @@ /*global MediumEditor, describe, it, expect */

describe('version', function () {
describe('MediumEditor.version', function () {

@@ -26,5 +26,29 @@ it('exists', function () {

});
});
describe('MediumEditor.parseVersionString', function () {
it('exists', function () {
expect(MediumEditor.parseVersionString).toBeTruthy();
});
it('parses a normal version string', function () {
var info = MediumEditor.parseVersionString('1.2.3');
expect(info.major).toBe(1);
expect(info.minor).toBe(2);
expect(info.revision).toBe(3);
expect(info.preRelease).toBe('');
});
it('parses pre-release versions', function () {
var info = MediumEditor.parseVersionString('5.0.0-alpha.1');
expect(info.major).toBe(5);
expect(info.minor).toBe(0);
expect(info.revision).toBe(0);
expect(info.preRelease).toBe('alpha.1');
});
});
});

@@ -1,5 +0,3 @@

/*global Util, ButtonsData, Selection, Extension,
extensionDefaults, Toolbar, Events, editorDefaults,
DefaultButton, AnchorExtension, FontSizeExtension,
AnchorPreviewDeprecated*/
/*global Util, Selection, Extension,
extensionDefaults, Events, editorDefaults*/

@@ -143,3 +141,3 @@ function MediumEditor(elements, options) {

if (node.getAttribute('data-medium-element') && node.children.length === 0) {
if (node.getAttribute('data-medium-editor-element') && node.children.length === 0) {
this.options.ownerDocument.execCommand('formatBlock', false, 'p');

@@ -164,2 +162,33 @@ }

function addToEditors(win) {
if (!win._mediumEditors) {
// To avoid breaking users who are assuming that the unique id on
// medium-editor elements will start at 1, inserting a 'null' in the
// array so the unique-id can always map to the index of the editor instance
win._mediumEditors = [null];
}
// If this already has a unique id, re-use it
if (!this.id) {
this.id = win._mediumEditors.length;
}
win._mediumEditors[this.id] = this;
}
function removeFromEditors(win) {
if (!win._mediumEditors || !win._mediumEditors[this.id]) {
return;
}
/* Setting the instance to null in the array instead of deleting it allows:
* 1) Each instance to preserve its own unique-id, even after being destroyed
* and initialized again
* 2) The unique-id to always correspond to an index in the array of medium-editor
* instances. Thus, we will be able to look at a contenteditable, and determine
* which instance it belongs to, by indexing into the global array.
*/
win._mediumEditors[this.id] = null;
}
function createElementsArray(selector) {

@@ -201,14 +230,8 @@ if (!selector) {

function initExtension(extension, name, instance) {
if (typeof extension.parent !== 'undefined') {
Util.warn('Extension .parent property has been deprecated. ' +
'The .base property for extensions will always be set to MediumEditor in version 5.0.0');
}
var extensionDefaults = {
'window': instance.options.contentWindow,
'document': instance.options.ownerDocument
'document': instance.options.ownerDocument,
'base': instance
};
// TODO: Deprecated (Remove .parent check in v5.0.0)
if (extension.parent !== false) {
extensionDefaults.base = instance;
}
// Add default options into the extension

@@ -219,4 +242,3 @@ extension = setExtensionDefaults(extension, extensionDefaults);

if (typeof extension.init === 'function') {
// Passing instance into init() will be deprecated in v5.0.0
extension.init(instance);
extension.init();
}

@@ -231,63 +253,39 @@

function shouldAddDefaultAnchorPreview() {
var i,
shouldAdd = false;
// TODO: deprecated
// If anchor-preview is disabled, don't add
if (this.options.disableAnchorPreview) {
function isToolbarEnabled() {
// If any of the elements don't have the toolbar disabled
// We need a toolbar
if (this.elements.every(function (element) {
return !!element.getAttribute('data-disable-toolbar');
})) {
return false;
}
// If anchor-preview is disabled, don't add
if (this.options.anchorPreview === false) {
return false;
}
// If anchor-preview extension has been overriden, don't add
if (this.options.extensions['anchor-preview']) {
return false;
}
// If toolbar is disabled, don't add
if (this.options.disableToolbar) {
return false;
}
// If all elements have 'data-disable-toolbar' attribute, don't add
for (i = 0; i < this.elements.length; i += 1) {
if (!this.elements[i].getAttribute('data-disable-toolbar')) {
shouldAdd = true;
break;
}
}
return shouldAdd;
return this.options.toolbar !== false;
}
function shouldAddDefaultPlaceholder() {
if (this.options.extensions['placeholder']) {
function isAnchorPreviewEnabled() {
// If toolbar is disabled, don't add
if (!isToolbarEnabled.call(this)) {
return false;
}
// TODO: deprecated
if (this.options.disablePlaceholders) {
return false;
}
return this.options.anchorPreview !== false;
}
function isPlaceholderEnabled() {
return this.options.placeholder !== false;
}
function shouldAddDefaultAutoLink() {
if (this.options.extensions['auto-link']) {
return false;
}
function isAutoLinkEnabled() {
return this.options.autoLink !== false;
}
function shouldAddDefaultImageDragging() {
if (this.options.extensions['image-dragging']) {
return false;
}
function isImageDraggingEnabled() {
return this.options.imageDragging !== false;
}
function isKeyboardCommandsEnabled() {
return this.options.keyboardCommands !== false;
}
function createContentEditable(textarea) {

@@ -332,3 +330,3 @@ var div = this.options.ownerDocument.createElement('div'),

}
element.setAttribute('data-medium-element', true);
element.setAttribute('data-medium-editor-element', true);
element.setAttribute('role', 'textbox');

@@ -350,17 +348,2 @@ element.setAttribute('aria-multiline', true);

function initToolbar() {
if (this.toolbar || this.options.disableToolbar) {
return false;
}
var addToolbar = this.elements.some(function (element) {
return !element.getAttribute('data-disable-toolbar');
});
if (addToolbar) {
this.toolbar = new Toolbar(this);
this.options.elementsContainer.appendChild(this.toolbar.getToolbarElement());
}
}
function attachHandlers() {

@@ -399,108 +382,42 @@ var i;

function initPlaceholder(options) {
// Backwards compatability
var defaultsBC = {
text: (typeof this.options.placeholder === 'string') ? this.options.placeholder : undefined // deprecated
};
function initExtensions() {
return new MediumEditor.extensions.placeholder(
Util.extend({}, options, defaultsBC)
);
}
this.extensions = [];
function initAnchorPreview(options) {
// Backwards compatability
var defaultsBC = {
hideDelay: this.options.anchorPreviewHideDelay, // deprecated
diffLeft: this.options.diffLeft, // deprecated (should use .getEditorOption() instead)
diffTop: this.options.diffTop, // deprecated (should use .getEditorOption() instead)
elementsContainer: this.options.elementsContainer // deprecated (should use .getEditorOption() instead)
};
// Passed in extensions
Object.keys(this.options.extensions).forEach(function (name) {
// Always save the toolbar extension for last
if (name !== 'toolbar' && this.options.extensions[name]) {
this.extensions.push(initExtension(this.options.extensions[name], name, this));
}
}, this);
return new MediumEditor.extensions.anchorPreview(
Util.extend({}, options, defaultsBC)
);
}
function initAnchorForm(options) {
// Backwards compatability
var defaultsBC = {
customClassOption: this.options.anchorButton ? (this.options.anchorButtonClass || 'btn') : undefined, // deprecated
linkValidation: this.options.checkLinkFormat, //deprecated
placeholderText: this.options.anchorInputPlaceholder, // deprecated
targetCheckbox: this.options.anchorTarget, // deprecated
targetCheckboxText: this.options.anchorInputCheckboxLabel // deprecated
// Built-in extensions
var builtIns = {
paste: true,
anchorPreview: isAnchorPreviewEnabled.call(this),
autoLink: isAutoLinkEnabled.call(this),
imageDragging: isImageDraggingEnabled.call(this),
keyboardCommands: isKeyboardCommandsEnabled.call(this),
placeholder: isPlaceholderEnabled.call(this)
};
return new MediumEditor.extensions.anchor(
Util.extend({}, options, defaultsBC)
);
}
function initPasteHandler(options) {
// Backwards compatability
var defaultsBC = {
forcePlainText: this.options.forcePlainText, // deprecated
cleanPastedHTML: this.options.cleanPastedHTML, // deprecated
disableReturn: this.options.disableReturn, // deprecated (should use .getEditorOption() instead)
targetBlank: this.options.targetBlank // deprecated (should use .getEditorOption() instead)
};
return new MediumEditor.extensions.paste(
Util.extend({}, options, defaultsBC)
);
}
function initCommands() {
var buttons = this.options.buttons,
extensions = this.options.extensions,
ext,
name;
this.commands = [];
buttons.forEach(function (buttonName) {
if (extensions[buttonName]) {
ext = initExtension(extensions[buttonName], buttonName, this);
this.commands.push(ext);
} else if (buttonName === 'anchor') {
ext = initExtension(initAnchorForm.call(this, this.options.anchor), 'anchor', this);
this.commands.push(ext);
} else if (buttonName === 'fontsize') {
ext = initExtension(new MediumEditor.extensions.fontSize(), buttonName, this);
this.commands.push(ext);
} else if (ButtonsData.hasOwnProperty(buttonName)) {
ext = initExtension(new MediumEditor.extensions.button(ButtonsData[buttonName]), buttonName, this);
this.commands.push(ext);
Object.keys(builtIns).forEach(function (name) {
if (builtIns[name]) {
this.addBuiltInExtension(name);
}
}, this);
for (name in extensions) {
if (extensions.hasOwnProperty(name) && buttons.indexOf(name) === -1) {
ext = initExtension(extensions[name], name, this);
this.commands.push(ext);
}
// Users can pass in a custom toolbar extension
// so check for that first and if it's not present
// just create the default toolbar
var toolbarExtension = this.options.extensions['toolbar'];
if (!toolbarExtension && isToolbarEnabled.call(this)) {
toolbarExtension = new MediumEditor.extensions.toolbar(this.options.toolbar);
}
// Only add default paste extension if it wasn't overriden
if (!this.options.extensions['paste']) {
this.commands.push(initExtension(initPasteHandler.call(this, this.options.paste), 'paste', this));
// If the toolbar is not disabled, so we actually have an extension
// initialize it and add it to the extensions array
if (toolbarExtension) {
this.extensions.push(initExtension(toolbarExtension, 'toolbar', this));
}
// Add AnchorPreview as extension if needed
if (shouldAddDefaultAnchorPreview.call(this)) {
this.commands.push(initExtension(initAnchorPreview.call(this, this.options.anchorPreview), 'anchor-preview', this));
}
if (shouldAddDefaultAutoLink.call(this)) {
this.commands.push(initExtension(new MediumEditor.extensions.autoLink(), 'auto-link', this));
}
if (shouldAddDefaultImageDragging.call(this)) {
this.commands.push(initExtension(new MediumEditor.extensions.imageDragging(), 'image-dragging', this));
}
if (shouldAddDefaultPlaceholder.call(this)) {
var placeholderOpts = (typeof this.options.placeholder === 'string') ? {} : this.options.placeholder;
this.commands.push(initExtension(initPlaceholder.call(this, placeholderOpts), 'placeholder', this));
}
}

@@ -510,15 +427,3 @@

var deprecatedProperties = [
['forcePlainText', 'paste.forcePlainText'],
['cleanPastedHTML', 'paste.cleanPastedHTML'],
['anchorInputPlaceholder', 'anchor.placeholderText'],
['checkLinkFormat', 'anchor.linkValidation'],
['anchorButton', 'anchor.customClassOption'],
['anchorButtonClass', 'anchor.customClassOption'],
['anchorTarget', 'anchor.targetCheckbox'],
['anchorInputCheckboxLabel', 'anchor.targetCheckboxText'],
['anchorPreviewHideDelay', 'anchorPreview.hideDelay'],
['disableAnchorPreview', 'anchorPreview: false'],
['disablePlaceholders', 'placeholder: false'],
['onShowToolbar', 'showToolbar custom event'],
['onHideToolbar', 'hideToolbar custom event']
// ['forcePlainText', 'paste.forcePlainText'],
];

@@ -529,9 +434,5 @@ // warn about using deprecated properties

if (options.hasOwnProperty(pair[0]) && options[pair[0]] !== undefined) {
Util.deprecated(pair[0], pair[1], 'v5.0.0');
Util.deprecated(pair[0], pair[1], 'v6.0.0');
}
});
if (options.hasOwnProperty('placeholder') && typeof options.placeholder === 'string') {
Util.deprecated('placeholder', 'placeholder.text', 'v5.0.0');
}
}

@@ -570,12 +471,2 @@

// deprecate
MediumEditor.statics = {
ButtonsData: ButtonsData,
DefaultButton: DefaultButton,
AnchorExtension: AnchorExtension,
FontSizeExtension: FontSizeExtension,
Toolbar: Toolbar,
AnchorPreview: AnchorPreviewDeprecated
};
MediumEditor.Extension = Extension;

@@ -592,4 +483,2 @@

init: function (elements, options) {
var uniqueId = 1;
this.options = mergeOptions.call(this, this.defaults, options);

@@ -602,8 +491,2 @@ this.origElements = elements;

while (this.options.elementsContainer.querySelector('#medium-editor-toolbar-' + uniqueId)) {
uniqueId = uniqueId + 1;
}
this.id = uniqueId;
return this.setup();

@@ -618,2 +501,3 @@ },

createElementsArray.call(this, this.origElements);
if (this.elements.length === 0) {

@@ -623,9 +507,10 @@ return;

this.events = new Events(this);
this.isActive = true;
addToEditors.call(this, this.options.contentWindow);
this.events = new Events(this);
// Call initialization helpers
initElements.call(this);
initCommands.call(this);
initToolbar.call(this);
initExtensions.call(this);
attachHandlers.call(this);

@@ -641,16 +526,8 @@ },

this.commands.forEach(function (extension) {
this.extensions.forEach(function (extension) {
if (typeof extension.destroy === 'function') {
extension.destroy();
} else if (typeof extension.deactivate === 'function') {
Util.warn('Extension .deactivate() function has been deprecated. Use .destroy() instead. This will be removed in version 5.0.0');
extension.deactivate();
}
}, this);
if (this.toolbar !== undefined) {
this.toolbar.destroy();
delete this.toolbar;
}
this.elements.forEach(function (element) {

@@ -664,3 +541,3 @@ // Reset elements content, fix for issue where after editor destroyed the red underlines on spelling errors are left

element.removeAttribute('spellcheck');
element.removeAttribute('data-medium-element');
element.removeAttribute('data-medium-editor-element');

@@ -682,2 +559,3 @@ // Remove any elements created for textareas

this.events.destroy();
removeFromEditors.call(this, this.options.contentWindow);
},

@@ -701,7 +579,2 @@

createEvent: function () {
Util.warn('.createEvent() has been deprecated and is no longer needed. ' +
'You can attach and trigger custom events without calling this method. This will be removed in v5.0.0');
},
trigger: function (name, data, editable) {

@@ -735,4 +608,4 @@ this.events.triggerCustomEvent(name, data, editable);

var extension;
if (this.commands && this.commands.length) {
this.commands.some(function (ext) {
if (this.extensions && this.extensions.length) {
this.extensions.some(function (ext) {
if (ext.name === name) {

@@ -749,27 +622,49 @@ extension = ext;

/**
* NOT DOCUMENTED - exposed for backwards compatability
* Helper function to call a method with a number of parameters on all registered extensions.
* The function assures that the function exists before calling.
*
* @param {string} funcName name of the function to call
* @param [args] arguments passed into funcName
* NOT DOCUMENTED - exposed as a helper for other extensions to use
*/
callExtensions: function (funcName) {
if (arguments.length < 1) {
return;
addBuiltInExtension: function (name) {
var extension = this.getExtensionByName(name);
if (extension) {
return extension;
}
var args = Array.prototype.slice.call(arguments, 1),
ext,
name;
for (name in this.options.extensions) {
if (this.options.extensions.hasOwnProperty(name)) {
ext = this.options.extensions[name];
if (ext[funcName] !== undefined) {
ext[funcName].apply(ext, args);
switch (name) {
case 'anchor':
extension = new MediumEditor.extensions.anchor(this.options.anchor);
break;
case 'anchorPreview':
extension = new MediumEditor.extensions.anchorPreview(this.options.anchorPreview);
break;
case 'autoLink':
extension = new MediumEditor.extensions.autoLink();
break;
case 'fontsize':
extension = new MediumEditor.extensions.fontSize();
break;
case 'imageDragging':
extension = new MediumEditor.extensions.imageDragging();
break;
case 'keyboardCommands':
extension = new MediumEditor.extensions.keyboardCommands(this.options.keyboardCommands);
break;
case 'paste':
extension = new MediumEditor.extensions.paste(this.options.paste);
break;
case 'placeholder':
extension = new MediumEditor.extensions.placeholder(this.options.placeholder);
break;
default:
// All of the built-in buttons for MediumEditor are extensions
// so check to see if the extension we're creating is a built-in button
if (MediumEditor.extensions.button.isBuiltInButton(name)) {
extension = new MediumEditor.extensions.button(name);
}
}
break;
}
return this;
if (extension) {
this.extensions.push(initExtension(extension, name, this));
}
return extension;
},

@@ -787,4 +682,5 @@

checkSelection: function () {
if (this.toolbar) {
this.toolbar.checkState();
var toolbar = this.getExtensionByName('toolbar');
if (toolbar) {
toolbar.checkState();
}

@@ -854,17 +750,2 @@ return this;

// NOT DOCUMENTED - exposed as extension helper
hideToolbarDefaultActions: function () {
if (this.toolbar) {
this.toolbar.hideToolbarDefaultActions();
}
return this;
},
// NOT DOCUMENTED - exposed as extension helper and for backwards compatability
setToolbarPosition: function () {
if (this.toolbar) {
this.toolbar.setToolbarPosition();
}
},
selectAllContents: function () {

@@ -1054,12 +935,2 @@ var currNode = Selection.getSelectionElement(this.options.contentWindow);

// alias for setup - keeping for backwards compatability
activate: function () {
Util.deprecatedMethod.call(this, 'activate', 'setup', arguments, 'v5.0.0');
},
// alias for destroy - keeping for backwards compatability
deactivate: function () {
Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0');
},
cleanPaste: function (text) {

@@ -1066,0 +937,0 @@ this.getExtensionByName('paste').cleanPaste(text);

@@ -1,6 +0,6 @@

var ButtonsData;
var buttonDefaults;
(function () {
'use strict';
ButtonsData = {
buttonDefaults = {
'bold': {

@@ -17,4 +17,3 @@ name: 'bold',

contentDefault: '<b>B</b>',
contentFA: '<i class="fa fa-bold"></i>',
key: 'b'
contentFA: '<i class="fa fa-bold"></i>'
},

@@ -32,4 +31,3 @@ 'italic': {

contentDefault: '<b><i>I</i></b>',
contentFA: '<i class="fa fa-italic"></i>',
key: 'i'
contentFA: '<i class="fa fa-italic"></i>'
},

@@ -47,4 +45,3 @@ 'underline': {

contentDefault: '<b><u>U</u></b>',
contentFA: '<i class="fa fa-underline"></i>',
key: 'u'
contentFA: '<i class="fa fa-underline"></i>'
},

@@ -51,0 +48,0 @@ 'strikethrough': {

/*global Button, FormExtension,
AnchorForm, AnchorPreview, AutoLink,
FontSizeForm, ImageDragging, PasteHandler,
Placeholder */
FontSizeForm, KeyboardCommands, ImageDragging,
PasteHandler, Placeholder, Toolbar */

@@ -19,5 +19,7 @@ var extensionDefaults;

imageDragging: ImageDragging,
keyboardCommands: KeyboardCommands,
paste: PasteHandler,
placeholder: Placeholder
placeholder: Placeholder,
toolbar: Toolbar
};
})();

@@ -6,17 +6,11 @@ var editorDefaults;

editorDefaults = {
activeButtonClass: 'medium-editor-button-active',
allowMultiParagraphSelection: true,
buttons: ['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote'],
buttonLabels: false,
delay: 0,
diffLeft: 0,
diffTop: -10,
disableReturn: false,
disableDoubleReturn: false,
disableToolbar: false,
disableEditing: false,
autoLink: false,
toolbarAlign: 'center',
elementsContainer: false,
imageDragging: true,
standardizeSelectionStart: false,
contentWindow: window,

@@ -28,7 +22,4 @@ ownerDocument: document,

extensions: {},
activeButtonClass: 'medium-editor-button-active',
firstButtonClass: 'medium-editor-button-first',
lastButtonClass: 'medium-editor-button-last',
spellcheck: true
};
})();

@@ -316,3 +316,4 @@ /*global Util*/

updateFocus: function (target, eventObj) {
var toolbarEl = this.base.toolbar ? this.base.toolbar.getToolbarElement() : null,
var toolbar = this.base.getExtensionByName('toolbar'),
toolbarEl = toolbar ? toolbar.getToolbarElement() : null,
anchorPreview = this.base.getExtensionByName('anchor-preview'),

@@ -319,0 +320,0 @@ previewEl = (anchorPreview && anchorPreview.getPreviewElement) ? anchorPreview.getPreviewElement() : null,

@@ -252,3 +252,4 @@ var Extension;

'off',
'subscribe'
'subscribe',
'trigger'

@@ -255,0 +256,0 @@ ].forEach(function (helper) {

@@ -22,14 +22,6 @@ var AnchorPreview;

/* ----- internal options needed from base ----- */
diffLeft: 0, // deprecated (should use .getEditorOption() instead)
diffTop: -10, // deprecated (should use .getEditorOption() instead)
elementsContainer: false, // deprecated (should use .getEditorOption() instead)
init: function () {
this.anchorPreview = this.createPreview();
if (!this.elementsContainer) {
this.elementsContainer = this.document.body;
}
this.elementsContainer.appendChild(this.anchorPreview);
this.getEditorOption('elementsContainer').appendChild(this.anchorPreview);

@@ -70,7 +62,2 @@ this.attachToEditables();

// TODO: deprecate
deactivate: function () {
Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0');
},
hidePreview: function () {

@@ -111,2 +98,4 @@ this.anchorPreview.classList.remove('medium-editor-anchor-preview-active');

middleBoundary = (boundary.left + boundary.right) / 2,
diffLeft = this.diffLeft,
diffTop = this.diffTop,
halfOffsetWidth,

@@ -116,5 +105,10 @@ defaultLeft;

halfOffsetWidth = this.anchorPreview.offsetWidth / 2;
defaultLeft = this.diffLeft - halfOffsetWidth;
var toolbarExtension = this.base.getExtensionByName('toolbar');
if (toolbarExtension) {
diffLeft = toolbarExtension.diffLeft;
diffTop = toolbarExtension.diffTop;
}
defaultLeft = diffLeft - halfOffsetWidth;
this.anchorPreview.style.top = Math.round(buttonHeight + boundary.bottom - this.diffTop + this.window.pageYOffset - this.anchorPreview.offsetHeight) + 'px';
this.anchorPreview.style.top = Math.round(buttonHeight + boundary.bottom - diffTop + this.window.pageYOffset - this.anchorPreview.offsetHeight) + 'px';
if (middleBoundary < halfOffsetWidth) {

@@ -195,3 +189,2 @@ this.anchorPreview.style.left = defaultLeft + halfOffsetWidth + 'px';

if (this.anchorToPreview) {
//this.activeAnchor = this.anchorToPreview;
this.showPreview(this.anchorToPreview);

@@ -198,0 +191,0 @@ }

@@ -50,4 +50,9 @@ var AnchorForm;

contentFA: '<i class="fa fa-link"></i>',
key: 'k',
init: function () {
FormExtension.prototype.init.apply(this, arguments);
this.subscribe('editableKeydown', this.handleKeydown.bind(this));
},
// Called when the button the toolbar is clicked

@@ -73,5 +78,4 @@ // Overrides ButtonExtension.handleClick

// Called when user hits the defined shortcut (CTRL / COMMAND + K)
// Overrides Button.handleKeydown
handleKeydown: function (event) {
if (Util.isKey(event, this.key.charCodeAt(0)) && Util.isMetaCtrlKey(event)) {
if (Util.isKey(event, Util.keyCode.K) && Util.isMetaCtrlKey(event) && !event.shiftKey) {
this.handleClick(event);

@@ -147,5 +151,5 @@ }

this.base.saveSelection();
this.base.hideToolbarDefaultActions();
this.hideToolbarDefaultActions();
this.getForm().style.display = 'block';
this.base.setToolbarPosition();
this.setToolbarPosition();

@@ -169,7 +173,2 @@ input.value = linkValue || '';

// TODO: deprecate
deactivate: function () {
Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0');
},
// core methods

@@ -176,0 +175,0 @@

@@ -33,2 +33,4 @@ /*global Extension, Util */

init: function () {
Extension.prototype.init.apply(this, arguments);
this.disableEventHandling = false;

@@ -35,0 +37,0 @@ this.subscribe('editableKeypress', this.onKeypress.bind(this));

@@ -5,11 +5,100 @@ var Button;

/*global Util, Extension */
/*global Extension, buttonDefaults */
Button = Extension.extend({
/* Button Options */
/* action: [string]
* The action argument to pass to MediumEditor.execAction()
* when the button is clicked
*/
action: undefined,
/* aria: [string]
* The value to add as the aria-label attribute of the button
* element displayed in the toolbar.
* This is also used as the tooltip for the button
*/
aria: undefined,
/* tagNames: [Array]
* NOTE: This is not used if useQueryState is set to true.
*
* Array of element tag names that would indicate that this
* button has already been applied. If this action has already
* been applied, the button will be displayed as 'active' in the toolbar
*
* Example:
* For 'bold', if the text is ever within a <b> or <strong>
* tag that indicates the text is already bold. So the array
* of tagNames for bold would be: ['b', 'strong']
*/
tagNames: undefined,
/* style: [Object]
* NOTE: This is not used if useQueryState is set to true.
*
* A pair of css property & value(s) that indicate that this
* button has already been applied. If this action has already
* been applied, the button will be displayed as 'active' in the toolbar
* Properties of the object:
* prop [String]: name of the css property
* value [String]: value(s) of the css property
* multiple values can be separated by a '|'
*
* Example:
* For 'bold', if the text is ever within an element with a 'font-weight'
* style property set to '700' or 'bold', that indicates the text
* is already bold. So the style object for bold would be:
* { prop: 'font-weight', value: '700|bold' }
*/
style: undefined,
/* useQueryState: [boolean]
* Enables/disables whether this button should use the built-in
* document.queryCommandState() method to determine whether
* the action has already been applied. If the action has already
* been applied, the button will be displayed as 'active' in the toolbar
*
* Example:
* For 'bold', if this is set to true, the code will call:
* document.queryCommandState('bold') which will return true if the
* browser thinks the text is already bold, and false otherwise
*/
useQueryState: undefined,
/* contentDefault: [string]
* Default innerHTML to put inside the button
*/
contentDefault: undefined,
/* contentFA: [string]
* The innerHTML to use for the content of the button
* if the `buttonLabels` option for MediumEditor is set to 'fontawesome'
*/
contentFA: undefined,
/* buttonDefaults: [Object]
* Set of default config options for all of the built-in MediumEditor buttons
*/
defaults: buttonDefaults,
// The button constructor can optionally accept the name of a built-in button
// (ie 'bold', 'italic', etc.)
// When the name of a button is passed, it will initialize itself with the
// configuration for that button
constructor: function (options) {
if (Button.isBuiltInButton(options)) {
Extension.call(this, this.defaults[options]);
} else {
Extension.call(this, options);
}
},
init: function () {
Extension.prototype.init.apply(this, arguments);
this.button = this.createButton();
this.on(this.button, 'click', this.handleClick.bind(this));
if (this.key) {
this.subscribe('editableKeydown', this.handleKeydown.bind(this));
}
},

@@ -63,16 +152,2 @@

handleKeydown: function (event) {
var action;
if (Util.isKey(event, this.key.charCodeAt(0)) && Util.isMetaCtrlKey(event) && !event.shiftKey) {
event.preventDefault();
event.stopPropagation();
action = this.getAction();
if (action) {
this.execAction(action);
}
}
},
handleClick: function (event) {

@@ -144,2 +219,6 @@ event.preventDefault();

});
Button.isBuiltInButton = function (name) {
return (typeof name === 'string') && Button.prototype.defaults.hasOwnProperty(name);
};
}());

@@ -5,3 +5,3 @@ var FontSizeForm;

/*global FormExtension, Selection, Util */
/*global FormExtension, Selection */

@@ -16,2 +16,6 @@ FontSizeForm = FormExtension.extend({

init: function () {
FormExtension.prototype.init.apply(this, arguments);
},
// Called when the button the toolbar is clicked

@@ -54,5 +58,5 @@ // Overrides ButtonExtension.handleClick

this.base.saveSelection();
this.base.hideToolbarDefaultActions();
this.hideToolbarDefaultActions();
this.getForm().style.display = 'block';
this.base.setToolbarPosition();
this.setToolbarPosition();

@@ -76,7 +80,2 @@ input.value = fontSize || '';

// TODO: deprecate
deactivate: function () {
Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0');
},
// core methods

@@ -83,0 +82,0 @@

@@ -13,2 +13,7 @@ var FormExtension;

FormExtension = Button.extend({
init: function () {
Button.prototype.init.apply(this, arguments);
},
// default labels for the form buttons

@@ -47,4 +52,37 @@ formSaveLabel: '&#10003;',

*/
hideForm: noop
hideForm: noop,
/************************ Helpers ************************
* The following are helpers that are either set by MediumEditor
* during initialization, or are helper methods which either
* route calls to the MediumEditor instance or provide common
* functionality for all form extensions
*********************************************************/
/* hideToolbarDefaultActions: [function ()]
*
* Helper function which will hide the default contents of the
* toolbar, but leave the toolbar container in the same state
* to allow a form to display its custom contents inside the toolbar
*/
hideToolbarDefaultActions: function () {
var toolbar = this.base.getExtensionByName('toolbar');
if (toolbar) {
toolbar.hideToolbarDefaultActions();
}
},
/* setToolbarPosition: [function ()]
*
* Helper function which will update the size and position
* of the toolbar based on the toolbar content and the current
* position of the user's selection
*/
setToolbarPosition: function () {
var toolbar = this.base.getExtensionByName('toolbar');
if (toolbar) {
toolbar.setToolbarPosition();
}
}
});
})();

@@ -9,2 +9,4 @@ /*global Util, Extension */

init: function () {
Extension.prototype.init.apply(this, arguments);
this.subscribe('editableDrag', this.handleDrag.bind(this));

@@ -43,3 +45,3 @@ this.subscribe('editableDrop', this.handleDrop.bind(this));

id = 'medium-img-' + (+new Date());
Util.insertHTMLCommand(this.document, '<img class="medium-image-loading" id="' + id + '" />');
Util.insertHTMLCommand(this.document, '<img class="medium-editor-image-loading" id="' + id + '" />');

@@ -46,0 +48,0 @@ fileReader.onload = function () {

@@ -81,7 +81,5 @@ /*global Util, Selection, Extension */

/* ----- internal options needed from base ----- */
targetBlank: false, // deprecated (should use .getEditorOption() instead)
disableReturn: false, // deprecated (should use .getEditorOption() instead)
init: function () {
Extension.prototype.init.apply(this, arguments);
init: function () {
if (this.forcePlainText || this.cleanPastedHTML) {

@@ -124,3 +122,3 @@ this.subscribe('editablePaste', this.handlePaste.bind(this));

if (!(this.disableReturn || element.getAttribute('data-disable-return'))) {
if (!(this.getEditorOption('disableReturn') || element.getAttribute('data-disable-return'))) {
paragraphs = pastedPlain.split(/[\r\n]+/g);

@@ -209,3 +207,3 @@ // If there are no \r\n in data, don't wrap in <p>

if ('a' === workEl.tagName.toLowerCase() && this.targetBlank) {
if ('a' === workEl.tagName.toLowerCase() && this.getEditorOption('targetBlank')) {
Util.setTargetBlank(workEl);

@@ -212,0 +210,0 @@ }

@@ -24,2 +24,4 @@ var Placeholder;

init: function () {
Extension.prototype.init.apply(this, arguments);
this.initPlaceholders();

@@ -26,0 +28,0 @@ this.attachEventHandlers();

@@ -25,3 +25,3 @@ /*global Util */

return this.findMatchingSelectionParent(function (el) {
return el.getAttribute('data-medium-element');
return el.getAttribute('data-medium-editor-element');
}, contentWindow);

@@ -81,10 +81,10 @@ },

// by Tim Down
getSelectionHtml: function getSelectionHtml() {
getSelectionHtml: function getSelectionHtml(doc) {
var i,
html = '',
sel = this.options.contentWindow.getSelection(),
sel = doc.getSelection(),
len,
container;
if (sel.rangeCount) {
container = this.options.ownerDocument.createElement('div');
container = doc.createElement('div');
for (i = 0, len = sel.rangeCount; i < len; i += 1) {

@@ -91,0 +91,0 @@ container.appendChild(sel.getRangeAt(i).cloneContents());

@@ -8,27 +8,2 @@ /*global NodeFilter, console, Selection*/

// Params: Array, Boolean, Object
function getProp(parts, create, context) {
if (!context) {
context = window;
}
try {
for (var i = 0; i < parts.length; i++) {
var p = parts[i];
if (!(p in context)) {
if (create) {
context[p] = {};
} else {
return;
}
}
context = context[p];
}
return context;
} catch (e) {
// 'p in context' throws an exception when context is a number, boolean, etc. rather than an object,
// so in that corner case just return undefined (by having no return statement)
}
}
function copyInto(overwrite, dest) {

@@ -69,3 +44,4 @@ var prop,

SPACE: 32,
DELETE: 46
DELETE: 46,
K: 107
},

@@ -92,9 +68,4 @@

isKey: function (event, keys) {
var keyCode = event.which;
var keyCode = this.getKeyCode(event);
// getting the key code from event
if (null === keyCode) {
keyCode = event.charCode !== null ? event.charCode : event.keyCode;
}
// it's not an array let's just compare strings!

@@ -112,2 +83,13 @@ if (false === Array.isArray(keys)) {

getKeyCode: function (event) {
var keyCode = event.which;
// getting the key code from event
if (null === keyCode) {
keyCode = event.charCode !== null ? event.charCode : event.keyCode;
}
return keyCode;
},
parentElements: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre'],

@@ -125,12 +107,2 @@

derives: function derives(base, derived) {
var origPrototype = derived.prototype;
function Proto() { }
Proto.prototype = base.prototype;
derived.prototype = new Proto();
derived.prototype.constructor = base;
derived.prototype = copyInto(false, derived.prototype, origPrototype);
return derived;
},
// Find the next node in the DOM tree that represents any text that is being

@@ -244,3 +216,3 @@ // displayed directly next to the targetNode (passed as an argument)

// do not traverse upwards past the nearest containing editor
if (current.getAttribute('data-medium-element')) {
if (current.getAttribute('data-medium-editor-element')) {
return false;

@@ -282,3 +254,3 @@ }

toReplace.parentNode.childNodes.length === 1 &&
!toReplace.parentNode.getAttribute('data-medium-element')) {
!toReplace.parentNode.getAttribute('data-medium-editor-element')) {
toReplace = toReplace.parentNode;

@@ -310,20 +282,2 @@ }

getSelectionRange: function (ownerDocument) {
this.deprecated('Util.getSelectionRange', 'Selection.getSelectionRange', 'v5.0.0');
return Selection.getSelectionRange(ownerDocument);
},
getSelectionStart: function (ownerDocument) {
this.deprecated('Util.getSelectionStart', 'Selection.getSelectionStart', 'v5.0.0');
return Selection.getSelectionStart(ownerDocument);
},
getSelectionData: function (el) {
this.deprecated('Util.getSelectionData', 'Selection.getSelectionData', 'v5.0.0');
return Selection.getSelectionData(el);
},
execFormatBlock: function (doc, tagName) {

@@ -437,8 +391,2 @@ var selectionData = Selection.getSelectionData(Selection.getSelectionStart(doc));

unwrapElement: function (element) {
this.deprecated('unwrapElement', 'unwrap', 'v5.0.0');
this.unwrap(element, element.ownerDocument);
},
/* splitDOMTree

@@ -727,20 +675,4 @@ *

}
},
setObject: function (name, value, context) {
// summary:
// Set a property from a dot-separated string, such as 'A.B.C'
var parts = name.split('.'),
p = parts.pop(),
obj = getProp(parts, true, context);
return obj && p ? (obj[p] = value) : undefined; // Object
},
getObject: function (name, create, context) {
// summary:
// Get a property from a dot-separated string, such as 'A.B.C'
return getProp(name ? name.split('.') : [], create, context); // Object
}
};
}(window));
/*global MediumEditor */
MediumEditor.version = (function (major, minor, revision) {
MediumEditor.parseVersionString = function (release) {
var split = release.split('-'),
version = split[0].split('.'),
preRelease = (split.length > 1) ? split[1] : '';
return {
major: parseInt(major, 10),
minor: parseInt(minor, 10),
revision: parseInt(revision, 10),
major: parseInt(version[0], 10),
minor: parseInt(version[1], 10),
revision: parseInt(version[2], 10),
preRelease: preRelease,
toString: function () {
return [major, minor, revision].join('.');
return [[version[0], version[1], version[2]].join('.'), preRelease].join('-');
}
};
}).apply(this, ({
};
MediumEditor.version = MediumEditor.parseVersionString.call(this, ({
// grunt-bump looks for this:
'version': '4.12.1'
}).version.split('.'));
'version': '5.0.0-alpha.0'
}).version);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc