Skip to content

Commit

Permalink
merge newest changes into our fork (#2)
Browse files Browse the repository at this point in the history
* First ugly draft

Pasting works, second pasting fails.

* Log, log everything

* Revert change on dist file

* Revert some unecessary code change

* Fix jslint issues and errors thrown during tests

* Get custom paste working for every paste

* Get rid of the console logs from paste extension

* paste-handling: remove some member variables from paste handler

* paste-handling: re-enable default paste handling + remove keyboard timing

* paste-handling: use clipboard helper for regular paste + remove hasContentType helper

* paste-handling: revert demo

* paste-handling: Refactor handlePasteBinPaste to look similar to handlePaste

* paste-handling: refactor and reduce two paste handling paths

* ignore .idea

* Prevent Firefox NS_ERROR_FAILURE: on keyup

In Firefox if the editable is a node without children, then NS_ERROR_FAILURE: error thrown for every keyup until it gets a child node. 

Issue: yabwe#994

* Update core.js

* paste-handling: convert trimHTML into replacements

* Reuse selectRange helper method in other places

* paste-handling: extract methods that shouldn't be part of paste handler api

* Convert spaces to %20 in links if linkValidation is true for the anchor extension

* Added separate test verification if linkValidation is false

* Used encodeURI instead of replacing strings to catch other unwanted characters

* Updated documentation for linkValidation encoding update

* Rename RELEASE-PROCESS.md

* Add instructions for running tests on external fork PRs in saucelabs

* Updated test - Made the diff between input and validUrl only spaces

* Make correction to external fork steps

* Fix anchor test failure due to cross-browser issues

* paste-handling: Add first test for paste-bin

* paste-handling: cleanup pasteBin and fix defaultPrevented check

* paste-handling: Add some more core tests for keyboard paste

* paste-handling: Add tests to fully cover new functionality

* Fix IE bugs

* 5.15.1

* make event functions chainable

* allow multiple targets in attachDOMEvent and detachDOMEvent

* update docs

* Re-organize content.spec.js a bit

* Add Test and comment for fix for yabwe#994

*  Fix yabwe#1047 - Add 'positionedToolbar' custom event (yabwe#1050)

* Add failing test to reproduce yabwe#1047

* Fix yabwe#1047 - introduce positionedToolbar custom event

* Add tests for positionedToolbar custom event

* Add positionedToolbar to events documentation

* Reference bug number in anchor-preview test

* Fix typo in positionedToolbar event documentation

* 5.16.0

* replace break-all with break-word

* 5.16.1

* add issue and PR templates

* add jsbin and codepen to example link

* fix typo

* Fix yabwe#942 Add core checkContentChanged method and use it for button example

* Add tests for covering checkContentChanged

* Almost final attempt

* Update documentation for addElements and removeElements

* Standardize usage of array operation helpers for dyn-add-elements

* Get rid of reRunSetupListener and refactored setupListener's "editableInput" case. Also removed unnecessary functions in core and moved guid to utils

* Add textarea tests for addElements

* Convert elements into array for addElements and removeElements

* Refactor core internal helpers to not require 'this' references

* Add tests to cover destroy/setup bug with dynamic added/removed elements

* Support selector and nodelist for addElements + removeElements

* Don't worry about setup/destroy for add/removeElements just yet

* Add tests for calling removeElements with textareas

* Make sure textareas are cleaned up correctly in removeElements

* Add more add/remove elements examples to README

* Add more add/remove elements tests, including event handlers

* Add test for dynamically adding disable-return element

* Extract initElement helper from initElements

* Move textarea initializing into initElement

* Move attaching existing events to elements into initElement

* Have setup use addElements to share common code path

* Rename events.attachAllEvents for consistency

* Remove unneeded addElement method

* execActionInternal should pass opt to document.execCommand if action not match internal action

* Add test to verify fix for yabwe#869

* Add regex to paste to remove supportLists comment from Word

* 5.17.0

* Fix null pointer during the cleanupElement event

I ran into an issue that after manually adding elements to the editor (through addElements), and later deleting them again there (through removeElements) was a TypeError being thrown.

It appears that contentCache is not set when only using dynamically added elements, thus while removing that element it will run into an error resulting the element not being removed properly.

This checks if contentCache is set.

* Update events.js

* Update events.js

* Update events.js

* refactor MediumEditor.execAction to use opts.value as an argument pass through document.execCommand

* Fix failures from new tests in IE & Edge

* Deprecate .url, .size, and .name for execAction

* Update API.md with more details about arguments

* Add test to ensure bc for .url option for createLink

* 5.18.0

* Add test to ensure editablePaste is triggered on keyboard paste

* Add test to verify editablePaste is triggered on normal paste

* Ensure editablePaste is triggered on keyboard paste

* Ensure editablePaste always gets consistent data when called

* Allow preview to be shown on empty links

* 5.19.1

* Update tests to ensure unique ids when timestamp is same

* Remove broken code for adding index to textarea-div id

* Add the id of the editor instance to each element

* Add tests for removing element attr on destroy

* Add getEditorFromElement static helper

* Add getEditorByElement and version to API documentation

* Add getContent helper method

* Add documentation for getContent method

* documented the showOnEmptyLink option

* Add resetContent helper method

* Add documentation for resetContent

* Respect form.reset for textareas

* Fix bug in resetContent logic

* Add grunt to local packages and create NPM build script

* Add getInteractionElements to extension contract for preventing blur

* Add test failure for yabwe#1105

* Fix yabwe#1105

* Add documentation for getInteractionElements for extensions

* 5.20.0

* Fix test failure in Chrome 51

* Use class selector instead attribute selector

* Update tests to expect new medium-editor-element class

* Fix yabwe#234 - Cursor rendering incorrectly in firefox

* Improve documentation for toolbar.relativeContainer option

* Work around firefox test case failing in saucelabs only

* 5.20.2

* Add addElement custom event when elements are added

* Add documentation for addElement custom event

* Fix bug in paste handler introduced by 8bd8f8f

* Expose removeElement custom event

* Ensure placeholder extension initializes dynamically added elements

* Ensure placeholder extensions cleans up removed elements

* Undo changes from 8bd8f8f

* yabwe#1123 Fixes issue with electron environment

* 1123, adds strict check for object

* yabwe#1127 | Placeholder is visible when only empty table is in Editor.

* yabwe#1127 | Add Test cases

* 5.21.0
  • Loading branch information
rvetere authored Jul 9, 2016
1 parent 17e81b9 commit 8c5e58d
Show file tree
Hide file tree
Showing 50 changed files with 4,735 additions and 670 deletions.
21 changes: 21 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### Description

[Description of the bug or feature]

### Steps to reproduce

1. [First step]
2. [Second step]
3. [and so on...]

**Expected behavior:** [What you expected to happen]

**Actual behavior:** [What actually happened]

**Link to an example:** [If you're reporting a bug that's not reproducible on our [demo page](https://yabwe.github.io/medium-editor/demo.html), please try to reproduce it on [JSFiddle](https://jsfiddle.net/), [JS Bin](https://jsbin.com), [CodePen](http://codepen.io/) or a similar service and paste a link here]

### Versions

- medium-editor:
- browser:
- OS:
17 changes: 17 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
| Q | A
| ---------------- | ---
| Bug fix? | yes/no
| New feature? | yes/no
| BC breaks? | yes/no
| Deprecations? | yes/no
| New tests added? | yes/not needed
| Fixed tickets | comma-separated list of tickets fixed by the PR, if any
| License | MIT

### Description

[Description of the bug or feature]

--

#### Please, don't submit `/dist` files with your PR!
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ reports/
coverage/
._*

#PhpStorm IDE
.idea/
# IDE
.idea/
225 changes: 208 additions & 17 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
- [`MediumEditor(elements, options)`](#mediumeditorelements-options)
- [`destroy()`](#destroy)
- [`setup()`](#setup)
- [`addElements()`](#addelementselements)
- [`removeElements()`](#removeelementselements)
- [Event Functions](#event-functions)
- [`on(target, event, listener, useCapture)`](#ontarget-event-listener-usecapture)
- [`off(target, event, listener, useCapture)`](#offtarget-event-listener-usecapture)
- [`on(targets, event, listener, useCapture)`](#ontargets-event-listener-usecapture)
- [`off(targets, event, listener, useCapture)`](#offtargets-event-listener-usecapture)
- [`subscribe(name, listener)`](#subscribename-listener)
- [`unsubscribe(name, listener)`](#unsubscribename-listener)
- [`trigger(name, data, editable)`](#triggername-data-editable)
Expand All @@ -33,10 +35,16 @@
- [`pasteHTML(html, options)`](#pastehtmlhtml-options)
- [`queryCommandState(action)`](#querycommandstateaction)
- [Helper Functions](#helper-functions)
- [`checkContentChanged(editable)`](#checkContentChangededitable)
- [`delay(fn)`](#delayfn)
- [`getContent(index)`](#getcontentindex)
- [`getExtensionByName(name)`](#getextensionbynamename)
- [`resetContent(element)`](#resetcontentelement)
- [`serialize()`](#serialize)
- [`setContent(html, index)`](#setcontenthtml-index)
- [Static Functions/Properties](#static-functionsproperties)
- [`getEditorFromElement(element)`](#geteditorfromelementelement)
- [`version`](#version)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand All @@ -46,14 +54,17 @@

Creating an instance of MediumEditor will:
* Convert all passed in elements into `contenteditable` elements.
* For any `<textarea>` elements, hide the `<textarea>`, create a new `<div contenteditable=true>` element, and ensure the 2 elements remain sync'd.
* For any `<textarea>` elements:
* Hide the `<textarea>`
* Create a new `<div contenteditable=true>` element and add it to the elements array.
* Ensure the 2 elements remain sync'd.
* Initialize any custom extensions or buttons passed in.
* Create any additional elements needed.
* Setup all event handling needed to monitor the editable elements.

**Arguments**

_**elements** (`String` | `HTMLElement` | `Array`)_:
_**elements** (`String` | `HTMLElement` | `Array` | `NodeList` | `HTMLCollection`)_:

1. `String`: If passed as a string, this is used as a selector in a call to `document.querySelectorAll()` to find elements on the page. All results are stored in the internal list of **elements**.

Expand All @@ -80,18 +91,67 @@ Tear down the editor if already setup by doing the following:

Initialize this instance of the editor if it has been destroyed. This will reuse the `elements` selector and `options` object passed in when the editor was instantiated.

***
### `addElements(elements)`

Dynamically add one or more elements to an already initialized instance of MediumEditor.

Passing an elements or array of elements to `addElements(elements)` will:
* Add the given element or array of elements to the editor **elements**
* Ensure the element(s) are initialized with the proper attributes and event handlers as if the element had been passed during instantiation of the editor
* For any `<textarea>` elements:
* Hide the `<textarea>`
* Create a new `<div contenteditable=true>` element and add it to the editor **elements**
* Ensure the 2 elements remain sync'd.
* Be intelligent enough to run the necessary code only once per element, no matter how often you will call it

So, every element you pass to `addElements` will turn into a fully supported contenteditable too - even earlier calls to `editor.subscribe(..)`
for custom events will work on the newly added element(s).

**Arguments**

_**elements** (`String` | `HTMLElement` | `Array` | `NodeList` | `HTMLCollection`)_:

1. `String`: If passed as a string, this is used as a selector in a call to `document.querySelectorAll()` to find elements on the page.

2. `HTMLElement`: If passed as a single element, this will be the only element added to the editor **elements**.

3. `Array` | `NodeList` | `HTMLCollection`: If passed as an `Array`-like collection of `HTMLElement`s, all of these elements will be added to the editor **elements**.

***
### `removeElements(elements)`

Remove one or more elements from an already initialized instance of MediumEditor.

Passing an elements or array of elements to `removeElements(elements)` will:
* Remove the given element or array of elements from the internal `this.elements` array.
* Remove any added event handlers or attributes (with the exception of `contenteditable`).
* Unhide any `<textarea>` elements and remove any created `<div>` elements created for `<textarea>` elements.

Each element itself will remain a contenteditable - it will just remove all event handlers and all references to it so you can safely remove it from DOM.

**Arguments**

_**elements** (`String` | `HTMLElement` | `Array` | `NodeList` | `HTMLCollection`)_:

1. `String`: If passed as a string, this is used as a selector in a call to `document.querySelectorAll()` to find elements on the page.

2. `HTMLElement`: If passed as a single element, this will be the only element removed from the editor **elements**.

3. `Array` | `NodeList` | `HTMLCollection`: If passed as an `Array`-like collection of `HTMLElement`s, all of these elements will be removed from the editor **elements**.

***
## Event Functions

### `on(target, event, listener, useCapture)`
### `on(targets, event, listener, useCapture)`

Attaches an event listener to specific element via the browser's built-in `addEventListener(type, listener, useCapture)` API. However, this helper method also ensures that when MediumEditor is destroyed, this event listener will be automatically be detached from the DOM.
Attaches an event listener to a specific element or elements via the browser's built-in `addEventListener(type, listener, useCapture)` API. However, this helper method also ensures that when MediumEditor is destroyed, this event listener will be automatically be detached from the DOM.

**Arguments**

1. _**target** (`HTMLElement`)_:
1. _**targets** (`HTMLElement` / `NodeList`)_:

* Element to attach listener to via `addEventListener(type, listener, useCapture)`
* Element or elements to attach listener to via `addEventListener(type, listener, useCapture)`

2. _**event** (`String`)_:

Expand All @@ -106,15 +166,15 @@ Attaches an event listener to specific element via the browser's built-in `addEv
* useCapture argument for `addEventListener(type, listener, useCapture)`

***
### `off(target, event, listener, useCapture)`
### `off(targets, event, listener, useCapture)`

Detach an event listener from a specific element via the browser's built-in `removeEventListener(type, listener, useCapture)` API.
Detach an event listener from a specific element or elements via the browser's built-in `removeEventListener(type, listener, useCapture)` API.

**Arguments**

1. _**target** (`HTMLElement`)_:
1. _**targets** (`HTMLElement` / `NodeList`)_:

* Element to detach listener from via `removeEventListener(type, listener, useCapture)`
* Element or elements to detach listener from via `removeEventListener(type, listener, useCapture)`

2. _**event** (`String`)_:

Expand Down Expand Up @@ -227,6 +287,12 @@ Returns a reference to the editor **element** that currently has focus (if the e

Returns a reference to the editor **element** that the user's selection is currently within.

**Arguments**

1. _**range** (`Range`)_: _**OPTIONAL**_
* The `Range` to find the selection parent element within
* If no element is provided, the editor will use the current range within the selection of the editor's `contentWindow`

***
### `restoreSelection()`

Expand Down Expand Up @@ -269,25 +335,101 @@ Enable the toolbar to start updating based on the user's selection, after a call
### `cleanPaste(text)`
_convert text to plaintext and replace current selection with result_

**Arguments**

1. _**text** (`String`)_:

* Content to be pasted at the location of the current selection/cursor

***
### `createLink(opts)`
_creates a link via the native `document.execCommand('createLink')` command_

**Arguments**

1. _**opts** (`Object`)_:

* Object containing additional properties needed for creating a link

**Properties of 'opts'**

1. _**value** (`String`)_ _**REQUIRED**_
* The url to set as the `href` of the created link. A non-empty value must be provided for the link to be created.
2. _**target** (`String`)_
* Attribute to set as the `target` attribute of the created link. Passing 'self' or not passing this option at all are equivalent in that they will just ensure that `target="_blank"` will NOT be present on the created link.
* **NOTE** If the `targetBlank` option on the editor is set to true, the `target` property of opts will be ignored and `target="_blank"` will be added to all created links.
3. _**buttonClass** (`String`)_
* Class (or classes) to append to the `class` attribute of the created link.

##### Example

```js
editor.createLink({ value: 'https://github.com/yabwe/medium-editor', target: '_blank', buttonClass: 'medium-link' });
```

***
### `execAction(action, opts)`
_executes an built-in action via document.execCommand_

**Arguments**

1. _**action** (`String`)_:

* Action to be passed as the 'command' argument to `document.execCommand(command, showDefaultUI, value)`

2. _**opts** (`Object`)_ _**OPTIONAL**_:

* Object containing additional properties for specific commands

**Properties of 'opts'**

1. _**value** (`String`)_
* The value to pass as the 'value' argument to `document.execCommand(command, showDefaultUI, value)`
2. For 'createLink', the `opts` are passed directly to [`.createLink(opts)`]((#createlinkopts)) so see that method for additional options for that command

***
### `pasteHTML(html, options)`
_replace the current selection with html_

**Arguments**

1. _**html** (`String`)_:

* Content to be pasted at the location of the current selection/cursor

2. _**options** (`Object`)_ _**OPTIONAL**_:

* Optional overrides for `cleanTags` and/or `cleanAttrs` for removing specific element types (`cleanTags`) or specific attributes (`cleanAttrs`) from the inserted HTML. See [cleanTags](OPTIONS.md#cleantags) and [cleanAttrs](OPTIONS.md#cleanattrs) in OPTIONS.md for more information.

##### Example

```js
editor.pasteHTML('<p class="classy"><strong>Some Custom HTML</strong></p>', { cleanAttrs: ['class'], cleanTags: ['strong']});
```

***
### `queryCommandState(action)`
_wrapper around the browser's built in `document.queryCommandState(action)` for checking whether a specific action has already been applied to the selection._
_wrapper around the browser's built in `document.queryCommandState(command)` for checking whether a specific action has already been applied to the selection._

**Arguments**

1. _**action** (`String`)_:

* Action to be passed as the 'command' argument to `document.queryCommandState(command)`

***
## Helper Functions

### `checkContentChanged(editable)`

Trigger the editor to check for updates to the html, and trigger the `editableInput` event if needed.

**Arguments**

1. _**editable** (`HTMLElement`)_: _**OPTIONAL**_
* The `<div contenteditable=true></div>` element that contains the html that may have changed.
* If no element is provided, the editor will check the currently 'active' editor element (the element with focus).

### `delay(fn)`

Delay any function from being executed by the amount of time passed as the **delay** option.
Expand All @@ -298,6 +440,16 @@ Delay any function from being executed by the amount of time passed as the **del

* Function to delay execution for.

***
### `getContent(index)`

Returns the trimmed html content for the first editor **element**, or the **element** at `index`.

**Arguments**

1. _**index** (`integer`)_: _**OPTIONAL**_
* Index of the editor **element** to retrieve the content from. Defaults to 0 when not provided (returns content of the first editor **element**).

***
### `getExtensionByName(name)`

Expand All @@ -309,6 +461,17 @@ Get a reference to an extension with the specified name.

* The name of the extension to retrieve (ie `toolbar`).

***
### `resetContent(element)`

Reset the content of all editor **elements** to their value at the time they were added to the editor. If a specific editor **element** is provided, only the content of that element will be reset.

**Arguments**

1. _**element** (`DOMElement`)_: _**OPTIONAL**_

* Specific editor **element** to reset the content of.

***
### `serialize()`

Expand All @@ -317,13 +480,41 @@ Returns a JSON object including the content of each of the **elements** inside t
***
### `setContent(html, index)`

Sets the innerHTML content for the element at `index`.
Trigger the `editableInput` event.
Sets the html content for the first editor **element**, or the **element** at `index`. Ensures the the `editableInput` event is triggered.

**Arguments**

1. _**html** (`string`)_:
* The content to set the element to

2. _**index** (`integer`)_:
* Index of the element to set the content on. Defaults to 0 when not provided.
2. _**index** (`integer`)_: _**OPTIONAL**_
* Index of the editor **element** to set the content of. Defaults to 0 when not provided (sets content of the first editor **element**).

***
## Static Functions/Properties

### `getEditorFromElement(element)`

Given an editor **element**, retrieves the instance of MediumEditor which created/is monitoring the **element**

**Arguments**

1. _**element** (`DOMElement`)_:
* An editor **element** which is part of a MediumEditor instance

### `version`

Object containing data about the version of the current MediumEditor library

**Properties of 'version'**

1. _**major** (`Number`)_
* The major version number (ie the `3` in `"3.2.1"`)
2. _**minor** (`Number`)_
* The minor version number (ie the `2` in `"3.2.1"`)
3. _**revision** (`Number`)_
* The revision (aka "patch") version number (ie the `1` in `"3.2.1"`)
4. _**preRelease** (`String`)_
* The pre-release version tag (ie the `"rc.1"` in `"5.0.0-rc.1"`)
5. _**toString** (`Function`)_
* Returns the full version number as a string (ie `"5.0.0-rc.1"`)
Loading

0 comments on commit 8c5e58d

Please sign in to comment.