diff --git a/shared/gridicons.svg b/shared/gridicons.svg new file mode 100644 index 0000000000000..00f3e4ad9e9b6 --- /dev/null +++ b/shared/gridicons.svg @@ -0,0 +1,251 @@ + diff --git a/shared/index.css b/shared/index.css new file mode 100644 index 0000000000000..b807bb87ef24c --- /dev/null +++ b/shared/index.css @@ -0,0 +1,85 @@ +body { + background: #f3f6f8; + color: #2f4452; + font-family: Merriweather, Georgia, "Times New Roman", Times, serif; + font-size: 1.25em; + line-height: 1.5; + margin: 1em; +} + +a { + color: inherit; +} + +nav { + font-size: 16px; +} + +nav:target { + display: none; +} + +nav li.is-active { + font-weight: bold; +} + +#editor { + background: #fff; + margin: 5em auto; + outline: none; + padding: 5em; + width: 37.5em; +} + +#editor iframe { + max-width: 100%; + border: 0; +} + +#editor img { + max-width: 100%; + height: auto; +} + +#editor figure { + margin: 0; +} + +#editor figure.aligncenter { + display: block; + margin-left: auto; + margin-right: auto; +} + +#editor figure.alignleft { + float: left; + margin: 0.5em 1em 0.5em 0; + width: 50%; +} + +#editor figure.alignright { + float: right; + margin: 0.5em 0 0.5em 1em; + width: 50%; +} + +#editor figcaption { + font-size: 0.8em; + margin-top: 0.5em; +} + +#editor figure img { + display: block; +} + +#editor pre { + overflow: auto; +} + +#editor:after { + content: "."; + visibility: hidden; + display: block; + height: 0; + clear: both; +} diff --git a/shared/tinymce/clean-paste.js b/shared/tinymce/clean-paste.js new file mode 100644 index 0000000000000..d3763edfdaaec --- /dev/null +++ b/shared/tinymce/clean-paste.js @@ -0,0 +1,19 @@ +( function( tinymce ) { + tinymce.PluginManager.add( 'clean-paste', function( editor ) { + // To do: remove pasted classes but keep when internally pasted. + + editor.on( 'BeforePastePreProcess', function( event ) { + var content = event.content; + + // Remove all external styles + content = content.replace( /(<[^>]+) style="[^"]*"([^>]*>)/gi, '$1$2' ); + + // Keep internal styles + content = content.replace( /(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function( all, before, value, after ) { + return before + ' style="' + value + '"' + after; + } ); + + event.content = content; + } ); + } ); +} )( window.tinymce ); diff --git a/shared/tinymce/toolbar.js b/shared/tinymce/toolbar.js new file mode 100644 index 0000000000000..4af5555c8bea1 --- /dev/null +++ b/shared/tinymce/toolbar.js @@ -0,0 +1,390 @@ +( function( tinymce ) { + tinymce.ui.svgbutton = tinymce.ui.Button.extend( { + renderHtml: function() { + var id = this._id; + var prefix = this.classPrefix; + var icon = this.state.get( 'icon' ); + var text = this.state.get( 'text' ); + var html = ''; + + if ( icon && icon.indexOf( 'gridicons-' ) === 0 ) { + html += ( + '' + ); + } else if ( icon ) { + html += ''; + } + + if ( text ) { + this.classes.add( 'btn-has-text' ); + html += '' + this.encode( text ) + ''; + } + + return ( + '
(`) (backtick).
+ *
+ * If the transformation in unwanted, the user can undo the change by pressing backspace,
+ * using the undo shortcut, or the undo button in the toolbar.
+ *
+ * Setting for the patterns can be overridden by plugins by using the `tiny_mce_before_init` PHP filter.
+ * The setting name is `wptextpattern` and the value is an object containing override arrays for each
+ * patterns group. There are three groups: "space", "enter", and "inline". Example (PHP):
+ *
+ * add_filter( 'tiny_mce_before_init', 'my_mce_init_wptextpattern' );
+ * function my_mce_init_wptextpattern( $init ) {
+ * $init['wptextpattern'] = wp_json_encode( array(
+ * 'inline' => array(
+ * array( 'delimiter' => '**', 'format' => 'bold' ),
+ * array( 'delimiter' => '__', 'format' => 'italic' ),
+ * ),
+ * ) );
+ *
+ * return $init;
+ * }
+ *
+ * Note that setting this will override the default text patterns. You will need to include them
+ * in your settings array if you want to keep them working.
+ */
+( function( tinymce, setTimeout ) {
+ if ( tinymce.Env.ie && tinymce.Env.ie < 9 ) {
+ return;
+ }
+
+ /**
+ * Escapes characters for use in a Regular Expression.
+ *
+ * @param {String} string Characters to escape
+ *
+ * @return {String} Escaped characters
+ */
+ function escapeRegExp( string ) {
+ return string.replace( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&' );
+ }
+
+ tinymce.PluginManager.add( 'wptextpattern', function( editor ) {
+ var VK = tinymce.util.VK;
+ var settings = editor.settings.wptextpattern || {};
+
+ var spacePatterns = settings.space || [
+ { regExp: /^[*-]\s/, cmd: 'InsertUnorderedList' },
+ { regExp: /^1[.)]\s/, cmd: 'InsertOrderedList' }
+ ];
+
+ var enterPatterns = settings.enter || [
+ { start: '##', format: 'h2' },
+ { start: '###', format: 'h3' },
+ { start: '####', format: 'h4' },
+ { start: '#####', format: 'h5' },
+ { start: '######', format: 'h6' },
+ { start: '>', format: 'blockquote' },
+ { regExp: /^(-){3,}$/, element: 'hr' }
+ ];
+
+ var inlinePatterns = settings.inline || [
+ { delimiter: '`', format: 'code' }
+ ];
+
+ var canUndo;
+
+ editor.on( 'selectionchange', function() {
+ canUndo = null;
+ } );
+
+ editor.on( 'keydown', function( event ) {
+ if ( ( canUndo && event.keyCode === 27 /* ESCAPE */ ) || ( canUndo === 'space' && event.keyCode === VK.BACKSPACE ) ) {
+ editor.undoManager.undo();
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+
+ if ( VK.metaKeyPressed( event ) ) {
+ return;
+ }
+
+ if ( event.keyCode === VK.ENTER ) {
+ enter();
+ // Wait for the browser to insert the character.
+ } else if ( event.keyCode === VK.SPACEBAR ) {
+ setTimeout( space );
+ } else if ( event.keyCode > 47 && ! ( event.keyCode >= 91 && event.keyCode <= 93 ) ) {
+ setTimeout( inline );
+ }
+ }, true );
+
+ function inline() {
+ var rng = editor.selection.getRng();
+ var node = rng.startContainer;
+ var offset = rng.startOffset;
+ var startOffset;
+ var endOffset;
+ var pattern;
+ var format;
+ var zero;
+
+ // We need a non empty text node with an offset greater than zero.
+ if ( ! node || node.nodeType !== 3 || ! node.data.length || ! offset ) {
+ return;
+ }
+
+ var string = node.data.slice( 0, offset );
+ var lastChar = node.data.charAt( offset - 1 );
+
+ tinymce.each( inlinePatterns, function( p ) {
+ // Character before selection should be delimiter.
+ if ( lastChar !== p.delimiter.slice( -1 ) ) {
+ return;
+ }
+
+ var escDelimiter = escapeRegExp( p.delimiter );
+ var delimiterFirstChar = p.delimiter.charAt( 0 );
+ var regExp = new RegExp( '(.*)' + escDelimiter + '.+' + escDelimiter + '$' );
+ var match = string.match( regExp );
+
+ if ( ! match ) {
+ return;
+ }
+
+ startOffset = match[1].length;
+ endOffset = offset - p.delimiter.length;
+
+ var before = string.charAt( startOffset - 1 );
+ var after = string.charAt( startOffset + p.delimiter.length );
+
+ // test*test* => format applied
+ // test *test* => applied
+ // test* test* => not applied
+ if ( startOffset && /\S/.test( before ) ) {
+ if ( /\s/.test( after ) || before === delimiterFirstChar ) {
+ return;
+ }
+ }
+
+ // Do not replace when only whitespace and delimiter characters.
+ if ( ( new RegExp( '^[\\s' + escapeRegExp( delimiterFirstChar ) + ']+$' ) ).test( string.slice( startOffset, endOffset ) ) ) {
+ return;
+ }
+
+ pattern = p;
+
+ return false;
+ } );
+
+ if ( ! pattern ) {
+ return;
+ }
+
+ format = editor.formatter.get( pattern.format );
+
+ if ( format && format[0].inline ) {
+ editor.undoManager.add();
+
+ editor.undoManager.transact( function() {
+ node.insertData( offset, '\uFEFF' );
+
+ node = node.splitText( startOffset );
+ zero = node.splitText( offset - startOffset );
+
+ node.deleteData( 0, pattern.delimiter.length );
+ node.deleteData( node.data.length - pattern.delimiter.length, pattern.delimiter.length );
+
+ editor.formatter.apply( pattern.format, {}, node );
+
+ editor.selection.setCursorLocation( zero, 1 );
+ } );
+
+ // We need to wait for native events to be triggered.
+ setTimeout( function() {
+ canUndo = 'space';
+
+ editor.once( 'selectionchange', function() {
+ var offset;
+
+ if ( zero ) {
+ offset = zero.data.indexOf( '\uFEFF' );
+
+ if ( offset !== -1 ) {
+ zero.deleteData( offset, offset + 1 );
+ }
+ }
+ } );
+ } );
+ }
+ }
+
+ function firstTextNode( node ) {
+ var parent = editor.dom.getParent( node, 'p' ),
+ child;
+
+ if ( ! parent ) {
+ return;
+ }
+
+ while ( child = parent.firstChild ) {
+ if ( child.nodeType !== 3 ) {
+ parent = child;
+ } else {
+ break;
+ }
+ }
+
+ if ( ! child ) {
+ return;
+ }
+
+ if ( ! child.data ) {
+ if ( child.nextSibling && child.nextSibling.nodeType === 3 ) {
+ child = child.nextSibling;
+ } else {
+ child = null;
+ }
+ }
+
+ return child;
+ }
+
+ function space() {
+ var rng = editor.selection.getRng(),
+ node = rng.startContainer,
+ parent,
+ text;
+
+ if ( ! node || firstTextNode( node ) !== node ) {
+ return;
+ }
+
+ parent = node.parentNode;
+ text = node.data;
+
+ tinymce.each( spacePatterns, function( pattern ) {
+ var match = text.match( pattern.regExp );
+
+ if ( ! match || rng.startOffset !== match[0].length ) {
+ return;
+ }
+
+ editor.undoManager.add();
+
+ editor.undoManager.transact( function() {
+ node.deleteData( 0, match[0].length );
+
+ if ( ! parent.innerHTML ) {
+ parent.appendChild( document.createElement( 'br' ) );
+ }
+
+ editor.selection.setCursorLocation( parent );
+ editor.execCommand( pattern.cmd );
+ } );
+
+ // We need to wait for native events to be triggered.
+ setTimeout( function() {
+ canUndo = 'space';
+ } );
+
+ return false;
+ } );
+ }
+
+ function enter() {
+ var rng = editor.selection.getRng(),
+ start = rng.startContainer,
+ node = firstTextNode( start ),
+ i = enterPatterns.length,
+ text, pattern, parent;
+
+ if ( ! node ) {
+ return;
+ }
+
+ text = node.data;
+
+ while ( i-- ) {
+ if ( enterPatterns[ i ].start ) {
+ if ( text.indexOf( enterPatterns[ i ].start ) === 0 ) {
+ pattern = enterPatterns[ i ];
+ break;
+ }
+ } else if ( enterPatterns[ i ].regExp ) {
+ if ( enterPatterns[ i ].regExp.test( text ) ) {
+ pattern = enterPatterns[ i ];
+ break;
+ }
+ }
+ }
+
+ if ( ! pattern ) {
+ return;
+ }
+
+ if ( node === start && tinymce.trim( text ) === pattern.start ) {
+ return;
+ }
+
+ editor.once( 'keyup', function() {
+ editor.undoManager.add();
+
+ editor.undoManager.transact( function() {
+ if ( pattern.format ) {
+ editor.formatter.apply( pattern.format, {}, node );
+ node.replaceData( 0, node.data.length, ltrim( node.data.slice( pattern.start.length ) ) );
+ } else if ( pattern.element ) {
+ parent = node.parentNode && node.parentNode.parentNode;
+
+ if ( parent ) {
+ parent.replaceChild( document.createElement( pattern.element ), node.parentNode );
+ }
+ }
+ } );
+
+ // We need to wait for native events to be triggered.
+ setTimeout( function() {
+ canUndo = 'enter';
+ } );
+ } );
+ }
+
+ function ltrim( text ) {
+ return text ? text.replace( /^\s+/, '' ) : '';
+ }
+ } );
+} )( window.tinymce, window.setTimeout );
diff --git a/tinymce-single/index.html b/tinymce-single/index.html
new file mode 100644
index 0000000000000..e6a33a4d91a06
--- /dev/null
+++ b/tinymce-single/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+ Editor Blocks Demo (Single TinyMCE Instance)
+
+
+
+
+
+
+
+ 1.0 Is The Loneliest Number
+
+ Many entrepreneurs idolize Steve Jobs. He’s such a perfectionist, they say. Nothing leaves the doors of 1 Infinite Loop in Cupertino without a polish and finish that makes geeks everywhere drool. No compromise!
+
+
+
+ I like Apple for the opposite reason: they’re not afraid of getting a rudimentary 1.0 out into the world.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tinymce-single/tinymce/block.css b/tinymce-single/tinymce/block.css
new file mode 100644
index 0000000000000..73af591759877
--- /dev/null
+++ b/tinymce-single/tinymce/block.css
@@ -0,0 +1,448 @@
+#editor img::selection {
+ background-color: transparent;
+}
+
+#editor *[data-mce-selected="block"] {
+ outline: 2px solid #87a6bc;
+ outline-offset: 11px;
+ /*background-color: rgba( 135, 166, 188, 0.3 );
+ box-shadow: 0px 0px 0px 11px rgba( 135, 166, 188, 0.3 );
+ position: relative;*/
+}
+
+/*#editor *[data-mce-selected="block"]:before {
+ content: '';
+ border-top: 2px solid #87a6bc;
+ border-left: 2px solid #87a6bc;
+ border-right: 2px solid #87a6bc;
+ display: block;
+ position: absolute;
+ top: -14px;
+ left: -12px;
+ right: -12px;
+ bottom: -14px;
+}
+
+#editor *[data-mce-selected="block"] ~ [data-mce-selected="block"]:before {
+ border-top: none;
+ border-bottom: 2px solid #87a6bc;
+}*/
+
+#editor *[data-mce-selected="move"] {
+ color: #87a6bc;
+ outline: 1px dashed #87a6bc;
+ outline-offset: 11px;
+}
+
+#editor.is-moving-block > *:before {
+ content: '\21E2';
+ display: block;
+ position: absolute;
+ font-size: 24px;
+ /*background-color: #0087be;
+ padding: 0 3px;
+ border-radius: 3px;
+ color: #fff;*/
+ color: #87a6bc;
+ font-weight: normal;
+ margin-top: -24px;
+ left: 40px;
+}
+
+#editor.is-moving-block > .alignright:before,
+#editor.is-moving-block > [data-mce-selected="move"]:before,
+#editor.is-moving-block > [data-mce-selected="move"] + *:before {
+ content: '';
+}
+
+.mce-container,
+.mce-container *,
+.mce-container button,
+.mce-container button:focus,
+.mce-container button:hover,
+.mce-container button:active,
+.mce-container input {
+ -webkit-appearance: none;
+ background: transparent;
+ border: 0;
+ box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ color: inherit;
+ cursor: inherit;
+ direction: ltr;
+ float: none;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif;
+ font-size: 14px;
+ -webkit-font-smoothing: subpixel-antialiased;
+ -moz-osx-font-smoothing: auto;
+ font-weight: normal;
+ height: auto;
+ letter-spacing: normal;
+ line-height: normal;
+ margin: 0;
+ max-width: none;
+ outline: 0;
+ padding: 0;
+ position: static;
+ -webkit-tap-highlight-color: transparent;
+ text-align: left;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ transition: none;
+ -webkit-transition: none;
+ vertical-align: top;
+ white-space: nowrap;
+ width: auto;
+}
+
+.mce-tooltip {
+ display: none;
+}
+
+.mce-btn button::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+.mce-inline-toolbar-grp .mce-btn {
+ border: 1px solid transparent;
+ position: relative;
+ display: inline-block;
+ background: none;
+ border-radius: 2px;
+ margin: 2px;
+ color: #23282d;
+}
+
+.mce-inline-toolbar-grp .mce-btn:hover,
+.mce-inline-toolbar-grp .mce-btn:focus {
+ background-color: #fafafa;
+ border-color: #23282d;
+ -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
+ box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
+}
+
+.mce-inline-toolbar-grp .mce-btn.mce-active,
+.mce-inline-toolbar-grp .mce-btn:active {
+ background-color: #ebebeb;
+ border-color: #555d66;
+ -webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.3 );
+ box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.3 );
+}
+
+.mce-inline-toolbar-grp .mce-btn button {
+ padding: 1px 2px;
+ display: block;
+}
+
+svg.gridicon {
+ width: 24px;
+ height: 24px;
+ fill: #000;
+}
+
+.mce-inline-toolbar-grp .mce-btn.mce-primary {
+ background: #0085ba;
+ border-color: #0073aa #006799 #006799;
+ -webkit-box-shadow: 0 1px 0 #006799;
+ box-shadow: 0 1px 0 #006799;
+ text-decoration: none;
+}
+
+.mce-inline-toolbar-grp .mce-btn.mce-primary .mce-txt,
+.mce-inline-toolbar-grp .mce-btn.mce-primary .mce-ico {
+ color: #fff;
+ text-shadow: 0 -1px 1px #006799,
+ 1px 0 1px #006799,
+ 0 1px 1px #006799,
+ -1px 0 1px #006799;
+}
+
+.mce-inline-toolbar-grp .mce-btn.mce-primary svg {
+ fill: #fff;
+}
+
+.mce-flow-layout-item {
+ margin: 1px;
+}
+
+.mce-btn .mce-txt {
+ display: block;
+ height: 24px;
+ min-width: 24px;
+ text-align: center;
+ font-size: 18px;
+ font-weight: 500;
+ line-height: 24px;
+}
+
+.mce-btn select {
+ width: 26px;
+ padding: 0;
+ border: 0;
+ height: 24px;
+ opacity: 0;
+ -webkit-appearance: none;
+ position: absolute;
+ top: 0;
+}
+
+div.mce-inline-toolbar-grp {
+ background-color: #f5f5f5;
+ border: 1px solid #a0a5aa;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ -webkit-box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.15 );
+ box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.15 );
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ margin-bottom: 8px;
+ position: absolute;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ max-width: 98%;
+ z-index: 99998; /* Under adminbar */
+}
+
+div.mce-inline-toolbar-grp > div.mce-stack-layout {
+ padding: 1px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-up {
+ margin-bottom: 0;
+ margin-top: 8px;
+}
+
+div.mce-inline-toolbar-grp:before,
+div.mce-inline-toolbar-grp:after {
+ position: absolute;
+ left: 50%;
+ display: block;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ border-color: transparent;
+ content: '';
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-up:before {
+ top: -9px;
+ border-bottom-color: #a0a5aa;
+ border-width: 0 9px 9px;
+ margin-left: -9px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-down:before {
+ bottom: -9px;
+ border-top-color: #a0a5aa;
+ border-width: 9px 9px 0;
+ margin-left: -9px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-up:after {
+ top: -8px;
+ border-bottom-color: #f5f5f5;
+ border-width: 0 8px 8px;
+ margin-left: -8px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-down:after {
+ bottom: -8px;
+ border-top-color: #f5f5f5;
+ border-width: 8px 8px 0;
+ margin-left: -8px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-left:before,
+div.mce-inline-toolbar-grp.mce-arrow-left:after {
+ margin: 0;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-left:before {
+ left: 20px;
+}
+div.mce-inline-toolbar-grp.mce-arrow-left:after {
+ left: 21px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-right:before,
+div.mce-inline-toolbar-grp.mce-arrow-right:after {
+ left: auto;
+ margin: 0;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-right:before {
+ right: 20px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-right:after {
+ right: 21px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-full {
+ right: 0;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-full > div {
+ width: 100%;
+ overflow-x: auto;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-left-side:before,
+div.mce-inline-toolbar-grp.mce-arrow-left-side:after {
+ left: auto;
+ top: 50%;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-left-side:before {
+ left: -9px;
+ border-right-color: #a0a5aa;
+ border-width: 9px 9px 9px 0;
+ margin-top: -9px;
+}
+
+div.mce-inline-toolbar-grp.mce-arrow-left-side:after {
+ left: -8px;
+ border-right-color: #f5f5f5;
+ border-width: 8px 8px 8px 0;
+ margin-top: -8px;
+}
+
+div.wp-link-preview {
+ float: left;
+ margin: 2px;
+ max-width: 694px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+div.wp-link-preview a {
+ display: block;
+ color: #0073aa;
+ font-size: 16px;
+ padding: 5px;
+ text-decoration: underline;
+ -webkit-transition-property: border, background, color;
+ transition-property: border, background, color;
+ -webkit-transition-duration: .05s;
+ transition-duration: .05s;
+ -webkit-transition-timing-function: ease-in-out;
+ transition-timing-function: ease-in-out;
+ cursor: pointer;
+}
+
+div.wp-link-input {
+ float: left;
+ margin: 2px;
+ max-width: 694px;
+}
+
+div.wp-link-input input {
+ font-size: 16px;
+ width: 300px;
+ padding: 4px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ border-width: 1px;
+ border-style: solid;
+ background-color: #fff;
+ color: #333;
+ border-color: #ddd;
+ box-shadow: inset 0 1px 2px rgba(0,0,0,0.07);
+}
+
+div.wp-link-input input:focus {
+ -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.1);
+ box-shadow: 0 1px 2px rgba(0,0,0,0.1);
+ border-color: #999;
+}
+
+@media screen and ( max-width: 782px ) {
+ div.wp-link-preview {
+ margin: 8px 0 8px 5px;
+ max-width: 70%;
+ max-width: -webkit-calc(100% - 86px);
+ max-width: calc(100% - 86px);
+ }
+}
+
+div.mce-inline-toolbar-grp.block-toolbar {
+ border: none;
+ background: none;
+ box-shadow: none;
+}
+
+.mce-btn.mce-move-up {
+ position: absolute;
+ top: -10px;
+ left: -30px;
+}
+
+.mce-btn.mce-move-down {
+ position: absolute;
+ bottom: -10px;
+ left: -30px;
+}
+
+/*.mce-btn.mce-move-up,
+.mce-btn.mce-move-down {
+ float: left;
+ border: none;
+}
+
+.mce-btn.mce-move-up {
+ margin-bottom: 0;
+}
+
+.mce-btn.mce-move-down {
+ margin-top: 0;
+ position: absolute;
+ bottom: 2px;
+ left: 2px;
+}
+
+.mce-btn.mce-move-up:focus,
+.mce-btn.mce-move-down:focus,
+.mce-btn.mce-move-up:hover,
+.mce-btn.mce-move-down:hover {
+ background: none;
+ box-shadow: none;
+}
+
+.mce-btn.mce-move-up button,
+.mce-btn.mce-move-down button {
+ height: 12px;
+ padding: 1px;
+}
+
+.mce-move-up svg.gridicon,
+.mce-move-down svg.gridicon {
+ position: relative;
+ top: -6px;
+ width: 20px;
+}*/
+
+.block-toolbar .mce-btn {
+ margin: 0;
+}
+
+.block-toolbar .mce-btn:hover,
+.block-toolbar .mce-btn:active {
+ border-color: transparent;
+ background: none;
+ box-shadow: none;
+}
+
+.block-toolbar .mce-flow-layout-item {
+ margin: 0;
+}
+
+div.mce-inline-toolbar-grp.block-toolbar > div.mce-stack-layout {
+ padding: 0;
+}
diff --git a/tinymce-single/tinymce/block.js b/tinymce-single/tinymce/block.js
new file mode 100644
index 0000000000000..8c26fc85358cf
--- /dev/null
+++ b/tinymce-single/tinymce/block.js
@@ -0,0 +1,563 @@
+( function( tinymce ) {
+ tinymce.PluginManager.add( 'block', function( editor ) {
+ function focusToolbar( toolbar ) {
+ var node = toolbar.find( 'toolbar' )[0];
+ node && node.focus( true );
+ }
+
+ editor.on( 'preinit', function() {
+ var DOM = tinymce.DOM;
+ var element;
+ var blockToolbar;
+ var blockToolbars = {};
+ var blockSelection = false;
+
+ tinymce.each( '123456'.split(''), function( level ) {
+ editor.addCommand( 'heading' + level, function() {
+ editor.formatter.apply( 'h' + level );
+ editor.nodeChanged();
+ } );
+
+ editor.addButton( 'heading' + level, {
+ text: level,
+ cmd: 'heading' + level,
+ onpostrender: function() {
+ var button = this;
+
+ editor.on( 'nodechange', function( event ) {
+ button.active( element.nodeName === 'H' + level );
+ } );
+ }
+ } );
+ } );
+
+ editor.addButton( 'heading', {
+ icon: 'gridicons-heading',
+ cmd: 'heading1'
+ } );
+
+ editor.addCommand( 'removeheading', function() {
+ editor.formatter.apply( 'p' );
+ editor.nodeChanged();
+ });
+
+ editor.addButton( 'removeheading', {
+ icon: 'gridicons-posts',
+ cmd: 'removeheading'
+ } );
+
+ editor.addCommand( 'preformatted', function() {
+ editor.formatter.apply( 'pre' );
+ editor.nodeChanged();
+ } );
+
+ editor.addButton( 'preformatted', {
+ icon: 'gridicons-code',
+ cmd: 'preformatted'
+ } );
+
+ editor.addCommand( 'removepreformatted', function() {
+ editor.formatter.remove( 'pre' );
+ editor.nodeChanged();
+ });
+
+ editor.addButton( 'removepreformatted', {
+ icon: 'gridicons-posts',
+ cmd: 'removepreformatted'
+ } );
+
+ editor.addButton( 'syntax', {
+ text: 'syntax',
+ onclick: function() {}
+ } );
+
+ editor.addCommand( 'removeblockquote', function() {
+ editor.formatter.remove( 'blockquote' );
+ editor.nodeChanged();
+ });
+
+ editor.addButton( 'removeblockquote', {
+ icon: 'gridicons-posts',
+ cmd: 'removeblockquote'
+ } );
+
+ editor.addCommand( 'alignleft', function() {
+ editor.formatter.remove( 'alignleft' );
+ editor.formatter.remove( 'aligncenter' );
+ editor.formatter.remove( 'alignright' );
+
+ editor.nodeChanged();
+ });
+
+ editor.addButton( 'alignleft', {
+ icon: 'gridicons-align-left',
+ cmd: 'alignleft',
+ onpostrender: function() {
+ var button = this;
+
+ editor.on( 'nodechange', function( event ) {
+ button.active( ! editor.formatter.matchNode( element, 'aligncenter' ) &&
+ ! editor.formatter.matchNode( element, 'alignright' ) );
+ } );
+ }
+ } );
+
+ // Adjust icon of TinyMCE core buttons.
+ editor.buttons.aligncenter.icon = 'gridicons-align-center';
+ editor.buttons.alignright.icon = 'gridicons-align-right';
+ editor.buttons.blockquote.icon = 'gridicons-quote';
+ editor.buttons.bullist.icon = 'gridicons-list-unordered';
+ editor.buttons.numlist.icon = 'gridicons-list-ordered';
+
+ editor.addCommand( 'removelist', function() {
+ editor.selection.select( element );
+
+ if ( element.nodeName === 'UL' ) {
+ editor.execCommand( 'InsertUnorderedList' );
+ } else if ( element.nodeName === 'OL' ) {
+ editor.execCommand( 'InsertOrderedList' );
+ }
+
+ editor.nodeChanged();
+ });
+
+ editor.addButton( 'removelist', {
+ icon: 'gridicons-posts',
+ cmd: 'removelist'
+ } );
+
+ tinymce.each( [ 'left', 'center', 'right' ], function( position ) {
+ editor.addCommand( 'imgalign' + position, function() {
+ tinymce.each( [ 'left', 'center', 'right' ], function( position ) {
+ editor.formatter.remove( 'align' + position, element );
+ } );
+
+ editor.formatter.apply( 'align' + position, element );
+
+ editor.nodeChanged();
+ } );
+
+ editor.addButton( 'imgalign' + position, {
+ icon: 'gridicons-align-image-' + position,
+ cmd: 'imgalign' + position,
+ onPostRender: function() {
+ var button = this;
+
+ editor.on( 'nodechange', function( event ) {
+ element = event.parents[ event.parents.length - 1 ];
+
+ button.active( editor.$( element ).hasClass( 'align' + position ) );
+ } );
+ }
+ } );
+ } );
+
+ editor.addCommand( 'addfigcaption', function() {
+ if ( ! editor.$( element ).find( 'figcaption' ).length ) {
+ var figcaption = editor.$( '
' );
+
+ editor.undoManager.transact( function() {
+ editor.$( element ).append( figcaption );
+ editor.selection.setCursorLocation( figcaption[0], 0 );
+ } );
+ }
+ } );
+
+ editor.addCommand( 'removefigcaption', function() {
+ var figcaption = editor.$( element ).find( 'figcaption' );
+
+ if ( figcaption.length ) {
+ editor.undoManager.transact( function() {
+ figcaption.remove();
+ } );
+ }
+ } );
+
+ editor.addCommand( 'togglefigcaption', function() {
+ if ( editor.$( element ).find( 'figcaption' ).length ) {
+ editor.execCommand( 'removefigcaption' );
+ } else {
+ editor.execCommand( 'addfigcaption' );
+ }
+ } );
+
+ editor.addButton( 'togglefigcaption', {
+ icon: 'gridicons-caption',
+ cmd: 'togglefigcaption',
+ onPostRender: function() {
+ var button = this;
+
+ editor.on( 'nodechange', function( event ) {
+ element = event.parents[ event.parents.length - 1 ];
+
+ button.active( editor.$( element ).find( 'figcaption' ).length > 0 );
+ } );
+ }
+ } );
+
+ editor.addCommand( 'selectblock', function() {
+ editor.$( element ).attr( 'data-mce-selected', 'block' );
+ editor.nodeChanged();
+
+ editor.once('click keydown', function ( event ) {
+ if ( tinymce.util.VK.modifierPressed( event ) ) {
+ return;
+ }
+
+ editor.$('*[data-mce-selected="block"]').removeAttr('data-mce-selected');
+ editor.nodeChanged();
+ } );
+ } );
+
+ // editor.addCommand( 'moveblock', function() {
+ // blockSelection = false;
+
+ // } );
+
+ editor.addButton( 'moveblock', {
+ icon: 'gridicons-reblog',
+ onclick: function() {
+ editor.$( element ).attr( 'data-mce-selected', 'move' );
+ editor.$( editor.getBody() ).addClass( 'is-moving-block' );
+ editor.nodeChanged();
+ }
+ } );
+
+ editor.addButton( 'block', {
+ icon: 'gridicons-posts',
+ tooltip: 'Add Block',
+ cmd: 'selectblock',
+ onPostRender: function() {
+ var button = this;
+
+ editor.on( 'nodechange', function( event ) {
+ element = event.parents[ event.parents.length - 1 ];
+
+ tinymce.each( editor.settings.blocks, function( block, key ) {
+ if ( block.match( element ) ) {
+ button.icon( block.icon || '' );
+ button.text( block.text || '' );
+ }
+ } );
+ } );
+ }
+ });
+
+ editor.addCommand( 'removeblock', function() {
+ var $blocks = editor.$( '*[data-mce-selected="block"]' ).add( element );
+ var p = editor.$( '
' );
+
+ editor.undoManager.transact( function() {
+ $blocks.first().before( p );
+ editor.selection.setCursorLocation( p[0], 0 );
+ $blocks.remove();
+ } );
+
+ setTimeout( function() {
+ editor.$( p ).attr( 'data-mce-selected', null );
+ } );
+ } );
+
+ editor.addButton( 'removeblock', {
+ icon: 'gridicons-trash',
+ cmd: 'removeblock'
+ } );
+
+ editor.addCommand( 'up', function() {
+ $blocks = editor.$( '*[data-mce-selected="block"]' ).add( element );
+ rect = element.getBoundingClientRect();
+ $prev = $blocks.first().prev();
+
+ if ( $prev.length ) {
+ $blocks.last().after( $prev );
+ editor.nodeChanged();
+ window.scrollBy( 0, - rect.top + element.getBoundingClientRect().top );
+ }
+ } );
+
+ editor.addCommand( 'down', function() {
+ $blocks = editor.$( '*[data-mce-selected="block"]' ).add( element );
+ rect = element.getBoundingClientRect();
+ $next = $blocks.last().next();
+
+ if ( $next.length ) {
+ $blocks.first().before( $next );
+ editor.nodeChanged();
+ window.scrollBy( 0, - rect.top + element.getBoundingClientRect().top );
+ }
+ } );
+
+ editor.addButton( 'up', {
+ icon: 'gridicons-chevron-up',
+ tooltip: 'Up',
+ cmd: 'up',
+ classes: 'widget btn move-up'
+ } );
+
+ editor.addButton( 'down', {
+ icon: 'gridicons-chevron-down',
+ tooltip: 'Down',
+ cmd: 'down',
+ classes: 'widget btn move-down'
+ } );
+
+ blockToolbar = editor.wp._createToolbar( [ 'up', 'block', 'down' ] )
+
+ blockToolbar.$el.addClass('block-toolbar')
+
+ blockToolbar.reposition = function () {
+ if (!element) return
+
+ var toolbar = this.getEl()
+ var toolbarRect = toolbar.getBoundingClientRect()
+ var elementRect = element.getBoundingClientRect()
+
+ var contentRect = editor.getBody().getBoundingClientRect();
+
+ DOM.setStyles(toolbar, {
+ position: 'absolute',
+ left: contentRect.left + 50 + 'px',
+ top: elementRect.top + window.pageYOffset + 'px'
+ } );
+
+ this.show()
+ }
+
+ editor.on('blur', function () {
+ blockToolbar.hide()
+ } );
+
+ editor.on( 'nodechange', function( event ) {
+ var empty = (
+ editor.dom.isEmpty( event.element ) &&
+ ( event.element.nodeName === 'P' || (
+ event.element.nodeName === 'BR' &&
+ event.element.parentNode.nodeName === 'P'
+ ) )
+ );
+
+ element = event.parents[ event.parents.length - 1 ];
+
+ if ( ! empty && editor.dom.isBlock( element ) ) {
+ blockToolbar.reposition();
+ } else {
+ blockToolbar.hide();
+ }
+
+ if ( element.nodeName === 'FIGURE' ) {
+ editor.$( element ).attr( 'data-mce-selected', 'block' );
+
+ editor.once('click keydown', function ( event ) {
+ if ( tinymce.util.VK.modifierPressed( event ) ) {
+ return;
+ }
+
+ editor.$('*[data-mce-selected="block"]').removeAttr('data-mce-selected');
+ editor.nodeChanged();
+ } );
+ }
+
+ var range = editor.selection.getRng()
+
+ var $start = editor.$( editor.dom.getParent( range.startContainer, function( element ) {
+ return element.parentNode === editor.getBody();
+ } ) );
+
+ var $end = editor.$( editor.dom.getParent( range.endContainer, function( element ) {
+ return element.parentNode === editor.getBody();
+ } ) );
+
+ // Selection only has the start of a new block.
+ if ( $end[0] === range.endContainer && range.endOffset === 0 ) {
+ $end = $end.prev();
+ }
+
+ if ( ! empty && $start[0] !== $end[0] ) {
+ // $start.add( $start.nextUntil( $end ) ).add( $end ).attr( 'data-mce-selected', 'block' );
+
+ // editor.once('click keydown', function ( event ) {
+ // if ( tinymce.util.VK.modifierPressed( event ) ) {
+ // return;
+ // }
+
+ // editor.$('*[data-mce-selected="block"]').removeAttr('data-mce-selected');
+ // editor.nodeChanged();
+ // } );
+
+ return;
+ }
+
+ if ( ! empty && editor.$( element ).attr( 'data-mce-selected' ) === 'block' ) {
+ blockSelection = true;
+
+ tinymce.each( editor.settings.blocks, function( block, key ) {
+ if ( block.match( element ) ) {
+ blockToolbars[ key ].reposition();
+
+ if ( element.nodeName !== 'FIGURE' ) {
+ focusToolbar( blockToolbars[ key ] );
+ }
+ } else {
+ blockToolbars[ key ].hide();
+ }
+ } );
+ } else {
+ blockSelection = false;
+
+ tinymce.each( editor.settings.blocks, function( block, key ) {
+ blockToolbars[ key ].hide();
+ } );
+ }
+ } )
+
+ tinymce.each( editor.settings.blocks, function( block, key ) {
+ blockToolbars[ key ] = editor.wp._createToolbar( block.buttons );
+ blockToolbars[ key ].reposition = function () {
+ if (!element) return
+
+ var toolbar = this.getEl()
+ var toolbarRect = toolbar.getBoundingClientRect()
+ var elementRect = element.getBoundingClientRect()
+
+ var contentRect = editor.getBody().getBoundingClientRect();
+
+ DOM.setStyles(toolbar, {
+ position: 'absolute',
+ left: elementRect.left + 'px',
+ top: elementRect.top + window.pageYOffset - toolbarRect.height - 8 + 'px'
+ })
+
+ this.show()
+ }
+
+ blockToolbars[ key ].on( 'keydown', function( event ) {
+ if ( event.keyCode === 27 ) {
+ editor.$('*[data-mce-selected="block"]').removeAttr('data-mce-selected');
+ editor.nodeChanged();
+ editor.focus();
+ }
+
+ // if ( event.keyCode === tinymce.util.VK.DOWN ) {
+ // editor.execCommand( 'down' );
+ // event.preventDefault();
+ // event.stopImmediatePropagation();
+ // }
+
+ // if ( event.keyCode === tinymce.util.VK.UP ) {
+ // editor.execCommand( 'up' );
+ // event.preventDefaultntDefault();
+ // event.stopImmediatePropagation();
+ // }
+ }, true );
+ } );
+
+ editor.on( 'beforeexeccommand', function( event ) {
+ var block = blockSelection;
+
+ editor.once( 'nodechange', function( event ) {
+ setTimeout( function() {
+ if ( block ) {
+ editor.$('*[data-mce-selected="block"]').removeAttr('data-mce-selected');
+ editor.$( element ).attr( 'data-mce-selected', 'block' );
+ editor.nodeChanged();
+ }
+ } );
+ }, true );
+ } );
+
+ var prevEmpty;
+
+ // Throttle?
+ editor.on( 'keyup', function() {
+ var empty = editor.dom.isEmpty( element );
+
+ if ( ( empty && ! prevEmpty ) || ( ! empty && prevEmpty ) ) {
+ editor.nodeChanged()
+ }
+
+ prevEmpty = empty;
+ } );
+
+ editor.on( 'keydown', function( event ) {
+ if ( editor.$( element ).attr( 'data-mce-selected' ) === 'block' ) {
+ if ( event.keyCode === tinymce.util.VK.DOWN ) {
+ editor.execCommand( 'down' );
+ event.preventDefault();
+ }
+
+ if ( event.keyCode === tinymce.util.VK.UP ) {
+ editor.execCommand( 'up' );
+ event.preventDefault();
+ }
+ }
+ } );
+
+ var metaCount = 0;
+
+ editor.on( 'keydown', function( event ) {
+ var keyCode = event.keyCode;
+ var VK = tinymce.util.VK;
+
+ if ( element.nodeName === 'FIGURE' ) {
+ if ( keyCode === VK.ENTER ) {
+ editor.execCommand( 'addfigcaption' );
+ event.preventDefault();
+ }
+
+ if ( keyCode === VK.BACKSPACE ) {
+ var caretEl = editor.selection.getNode();
+
+ if ( caretEl.nodeName !== 'FIGCAPTION' ) {
+ editor.execCommand( 'removeblock' );
+ event.preventDefault();
+ } else {
+ var range = editor.selection.getRng();
+
+ if ( range.collapsed && range.startOffset === 0 ) {
+ editor.execCommand( 'removefigcaption' );
+ event.preventDefault();
+ }
+ }
+ }
+
+ if ( keyCode === VK.LEFT ) {
+ var range = editor.selection.getRng();
+
+ if ( keyCode === VK.LEFT && range.startOffset === 0 ) {
+ event.preventDefault();
+ }
+ }
+ }
+
+ if ( VK.metaKeyPressed( event ) ) {
+ metaCount ++;
+ } else {
+ metaCount = 0;
+ }
+
+ if ( keyCode === 27 ) {
+ editor.$('*[data-mce-selected="block"]').removeAttr('data-mce-selected');
+ editor.nodeChanged();
+ }
+ }, true );
+
+ editor.on( 'keyup', function( event ) {
+ if ( metaCount === 1 ) {
+ editor.execCommand( 'selectblock' );
+ }
+
+ metaCount = 0;
+ } );
+
+ editor.on( 'dragstart', function( event ) {
+ if ( element.nodeName === 'FIGURE' ) {
+ event.preventDefault();
+ }
+ } );
+ } );
+
+ editor.on( 'init', function() {
+ editor.focus();
+ } );
+ } );
+} )( window.tinymce );
diff --git a/tinymce-single/tinymce/config.js b/tinymce-single/tinymce/config.js
new file mode 100644
index 0000000000000..5d4b62f5cce32
--- /dev/null
+++ b/tinymce-single/tinymce/config.js
@@ -0,0 +1,111 @@
+window.tinymce.init( {
+ browser_spellcheck: true,
+ // Enter twice in a nested block creates a fresh paragraph.
+ end_container_on_empty_block: true,
+ inline: true,
+ // Enter creates a fresh paragraph.
+ keep_styles: false,
+ menubar: false,
+ object_resizing: false,
+ plugins: [
+ 'block',
+ 'new',
+ 'formatting',
+ 'clean-paste',
+ 'lists',
+ 'paste',
+ 'toolbar',
+ 'wplink',
+ 'wptextpattern'
+ ],
+ schema: 'html5-strict',
+ selector: '#editor',
+ theme: false,
+ toolbar: false,
+ formats: {
+ alignleft: [
+ {
+ selector: 'p,h1,h2,h3,h4,h5,h6',
+ styles: { textAlign: 'left' }
+ },
+ {
+ selector: 'figure',
+ classes: 'alignleft'
+ }
+ ],
+ aligncenter: [
+ {
+ selector: 'p,h1,h2,h3,h4,h5,h6',
+ styles: { textAlign: 'center' }
+ },
+ {
+ selector: 'figure',
+ classes: 'aligncenter'
+ }
+ ],
+ alignright: [
+ {
+ selector: 'p,h1,h2,h3,h4,h5,h6',
+ styles: { textAlign: 'right' }
+ },
+ {
+ selector: 'figure',
+ classes: 'alignright'
+ }
+ ],
+ strikethrough: { inline: 'del' }
+ },
+ blocks: {
+ paragraph: {
+ match: function( element ) {
+ return element.nodeName === 'P';
+ },
+ buttons: [ 'alignleft', 'aligncenter', 'alignright', 'heading', 'blockquote', 'bullist', 'preformatted', 'removeblock' ],
+ icon: 'gridicons-posts'
+ },
+ heading: {
+ match: function( element ) {
+ var nodeName = element.nodeName;
+
+ return (
+ nodeName === 'H1' ||
+ nodeName === 'H2' ||
+ nodeName === 'H3' ||
+ nodeName === 'H4' ||
+ nodeName === 'H5' ||
+ nodeName === 'H6'
+ );
+ },
+ buttons: [ 'alignleft', 'aligncenter', 'alignright', 'heading1', 'heading2', 'heading3', 'heading4', 'heading5', 'heading6', 'removeheading', 'removeblock' ],
+ icon: 'gridicons-heading'
+ },
+ list: {
+ match: function( element ) {
+ return element.nodeName === 'UL' || element.nodeName === 'OL';
+ },
+ buttons: [ 'bullist', 'numlist', 'removelist', 'removeblock' ],
+ icon: 'gridicons-list-unordered'
+ },
+ image: {
+ match: function( element ) {
+ return element.nodeName === 'FIGURE';
+ },
+ buttons: [ 'imgalignleft', 'imgaligncenter', 'imgalignright', 'togglefigcaption', 'removeblock' ],
+ icon: 'gridicons-image'
+ },
+ blockquote: {
+ match: function( element ) {
+ return element.nodeName === 'BLOCKQUOTE';
+ },
+ buttons: [ 'removeblockquote', 'removeblock' ],
+ icon: 'gridicons-quote'
+ },
+ preformatted: {
+ match: function( element ) {
+ return element.nodeName === 'PRE';
+ },
+ buttons: [ 'syntax', 'removepreformatted', 'removeblock' ],
+ icon: 'gridicons-code'
+ }
+ }
+} );
diff --git a/tinymce-single/tinymce/formatting.js b/tinymce-single/tinymce/formatting.js
new file mode 100644
index 0000000000000..63ef381c3ef0e
--- /dev/null
+++ b/tinymce-single/tinymce/formatting.js
@@ -0,0 +1,108 @@
+( function( tinymce ) {
+ tinymce.PluginManager.add( 'formatting', function( editor ) {
+ var each = tinymce.each
+ var DOM = tinymce.DOM
+
+ editor.on( 'preinit', function() {
+ // Adjust icon of TinyMCE core buttons.
+ editor.buttons.bold.icon = 'gridicons-bold';
+ editor.buttons.italic.icon = 'gridicons-italic';
+ editor.buttons.strikethrough.icon = 'gridicons-strikethrough';
+ editor.buttons.link.icon = 'gridicons-link';
+ } );
+
+ editor.on('focus', function () {
+ if (editor.wp && editor.wp._createToolbar) {
+ var element
+ var toolbarInline = editor.wp._createToolbar( [ 'bold', 'italic', 'strikethrough', 'link' ] )
+ var toolbarMulti = editor.wp._createToolbar( [ 'alignleft', 'aligncenter', 'alignright', 'blockquote', 'bullist', 'removeblock' ] )
+
+ toolbarMulti.reposition = function () {
+ if (!element) return
+
+ var toolbar = this.getEl()
+ var toolbarRect = toolbar.getBoundingClientRect()
+ var elementRect = element.getBoundingClientRect()
+
+ var contentRect = document.getElementById( 'content' ).getBoundingClientRect();
+
+ DOM.setStyles(toolbar, {
+ position: 'absolute',
+ left: elementRect.left + 'px',
+ top: elementRect.top + window.pageYOffset - toolbarRect.height - 8 + 'px'
+ })
+
+ this.show()
+ }
+
+ editor.on('wptoolbar', function (event) {
+ element = event.element
+ range = event.range
+
+ var content = editor.selection.getContent()
+ var parent = editor.dom.getParent(range.startContainer, '*[data-mce-selected="block"]')
+
+ // No collapsed selection.
+ if (range.collapsed) {
+ return
+ }
+
+ // No non editable elements.
+ if (
+ element.getAttribute('contenteditable') === 'false' ||
+ element.getAttribute('data-mce-bogus') === 'all'
+ ) {
+ return
+ }
+
+ // No images.
+ if (element.nodeName === 'IMG') {
+ return
+ }
+
+ // No horizontal rules.
+ if (element.nodeName === 'HR') {
+ return
+ }
+
+ // No links.
+ if (element.nodeName === 'A') {
+ return
+ }
+
+ // No empty selection.
+ if (!content.replace(/<[^>]+>/g, '').replace(/(?:\s| )/g, '')) {
+ return
+ }
+
+ // Block where the selection starts.
+ var $start = editor.$( editor.dom.getParent( range.startContainer, editor.dom.isBlock ) );
+ // Block where the selection ends.
+ var $end = editor.$( editor.dom.getParent( range.endContainer, editor.dom.isBlock ) );
+
+ // Selection end only has the start of a new block.
+ if ( $end[0] === range.endContainer && range.endOffset === 0 ) {
+ $end = $end.prev();
+ }
+
+ // Start and end blocks are not the same.
+ if ( $start[0] !== $end[0] ) {
+ event.toolbar = toolbarMulti
+ event.selection = range
+ } else if ( ! parent ) {
+ event.toolbar = toolbarInline
+ event.selection = range
+ }
+
+ // Click inside selection does not trigger nodechange.
+ editor.once( 'click', function ( event ) {
+ window.setTimeout( function() {
+ editor.$('*[data-mce-selected="block"]').removeAttr('data-mce-selected');
+ editor.nodeChanged();
+ } );
+ } );
+ })
+ }
+ })
+ } );
+} )( window.tinymce );
diff --git a/tinymce-single/tinymce/new.js b/tinymce-single/tinymce/new.js
new file mode 100644
index 0000000000000..f016d7740a220
--- /dev/null
+++ b/tinymce-single/tinymce/new.js
@@ -0,0 +1,56 @@
+( function( tinymce ) {
+ tinymce.PluginManager.add( 'new', function( editor ) {
+ var DOM = tinymce.DOM;
+
+ editor.addButton( 'add', {
+ icon: 'gridicons-add-outline',
+ tooltip: 'Add Block'
+ } );
+
+ editor.on('focus', function () {
+ if (editor.wp && editor.wp._createToolbar) {
+ var element
+ var toolbarCaret = editor.wp._createToolbar( [ 'add' ] )
+
+ toolbarCaret.$el.addClass('block-toolbar')
+
+ toolbarCaret.reposition = function () {
+ if (!element) return
+
+ var toolbar = this.getEl()
+ var toolbarRect = toolbar.getBoundingClientRect()
+ var elementRect = element.getBoundingClientRect()
+
+ var contentRect = editor.getBody().getBoundingClientRect();
+
+ DOM.setStyles(toolbar, {
+ position: 'absolute',
+ left: contentRect.left + 50 + 'px',
+ top: elementRect.top + window.pageYOffset + 'px'
+ // top: elementRect.top + window.pageYOffset + elementRect.height / 2 - toolbarRect.height / 2 + 'px'
+ })
+
+ this.show()
+ }
+
+ editor.on('blur', function () {
+ toolbarCaret.hide()
+ })
+
+ editor.on('wptoolbar', function (event) {
+ element = event.element
+ range = event.range
+
+ // No collapsed selection.
+ if (range.collapsed) {
+ if ( event.empty ) {
+ event.toolbar = toolbarCaret
+ }
+
+ return
+ }
+ } );
+ }
+ } );
+ } );
+} )( window.tinymce );